summaryrefslogtreecommitdiff
path: root/chromium/content/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-08 10:28:10 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-20 13:40:30 +0000
commite733310db58160074f574c429d48f8308c0afe17 (patch)
treef8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/content/browser
parent2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff)
downloadqtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/content/browser')
-rw-r--r--chromium/content/browser/BUILD.gn149
-rw-r--r--chromium/content/browser/DEPS14
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc133
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc6
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.cc6
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.h2
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc7
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc7
-rw-r--r--chromium/content/browser/accessibility/ax_platform_position.cc93
-rw-r--r--chromium/content/browser/accessibility/ax_platform_position.h38
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h27
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc79
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.cc5
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.h1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm86
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc188
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h68
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc82
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc18
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc19
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc1
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc15
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc3
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc13
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc106
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc2
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc9
-rw-r--r--chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc2
-rw-r--r--chromium/content/browser/android/app_web_message_port_message_filter.cc97
-rw-r--r--chromium/content/browser/android/app_web_message_port_message_filter.h57
-rw-r--r--chromium/content/browser/android/app_web_message_port_service_impl.cc251
-rw-r--r--chromium/content/browser/android/app_web_message_port_service_impl.h93
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc28
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.h7
-rw-r--r--chromium/content/browser/android/composited_touch_handle_drawable.cc2
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc220
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h45
-rw-r--r--chromium/content/browser/android/content_view_statics.cc5
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h1
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.h1
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object.cc4
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object.h4
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc2
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper.cc2
-rw-r--r--chromium/content/browser/android/java_interfaces_impl.cc14
-rw-r--r--chromium/content/browser/android/java_interfaces_impl.h4
-rw-r--r--chromium/content/browser/android/overscroll_controller_android.cc2
-rw-r--r--chromium/content/browser/android/synchronous_compositor_browser_filter.cc240
-rw-r--r--chromium/content/browser/android/synchronous_compositor_browser_filter.h91
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc114
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h31
-rw-r--r--chromium/content/browser/android/synchronous_compositor_observer.cc131
-rw-r--r--chromium/content/browser/android/synchronous_compositor_observer.h61
-rw-r--r--chromium/content/browser/android/url_request_content_job.h4
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc28
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.h7
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.cc30
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.h8
-rw-r--r--chromium/content/browser/appcache/appcache_group.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc31
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h6
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service_unittest.cc27
-rw-r--r--chromium/content/browser/background_sync/background_sync_context.cc10
-rw-r--r--chromium/content/browser/background_sync/background_sync_context.h6
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc2
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc4
-rw-r--r--chromium/content/browser/bad_message.cc2
-rw-r--r--chromium/content/browser/bad_message.h20
-rw-r--r--chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc4
-rw-r--r--chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc617
-rw-r--r--chromium/content/browser/blob_storage/blob_data_builder_unittest.cc31
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host.cc269
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host.h63
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc594
-rw-r--r--chromium/content/browser/blob_storage/blob_flattener_unittest.cc204
-rw-r--r--chromium/content/browser/blob_storage/blob_memory_controller_unittest.cc680
-rw-r--r--chromium/content/browser/blob_storage/blob_reader_unittest.cc42
-rw-r--r--chromium/content/browser/blob_storage/blob_slice_unittest.cc195
-rw-r--r--chromium/content/browser/blob_storage/blob_storage_context_unittest.cc355
-rw-r--r--chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc17
-rw-r--r--chromium/content/browser/blob_storage/blob_transport_host_unittest.cc512
-rw-r--r--chromium/content/browser/blob_storage/blob_transport_request_builder_unittest.cc (renamed from chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc)32
-rw-r--r--chromium/content/browser/blob_storage/blob_url_browsertest.cc2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc37
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h8
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc134
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blocklist.cc (renamed from chromium/content/browser/bluetooth/bluetooth_blacklist.cc)88
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blocklist.h (renamed from chromium/content/browser/bluetooth/bluetooth_blacklist.h)54
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blocklist_unittest.cc (renamed from chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc)263
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc219
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h11
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.cc49
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.h26
-rw-r--r--chromium/content/browser/bluetooth/cache_query_result.h13
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc195
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.h18
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc100
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h8
-rw-r--r--chromium/content/browser/browser_context.cc44
-rw-r--r--chromium/content/browser/browser_main_loop.cc127
-rw-r--r--chromium/content/browser/browser_main_loop.h9
-rw-r--r--chromium/content/browser/browser_main_runner.cc14
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc10
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.h8
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc155
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h15
-rw-r--r--chromium/content/browser/browser_thread_impl.cc24
-rw-r--r--chromium/content/browser/browser_thread_impl.h2
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc34
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc27
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h11
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.proto2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc64
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h27
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.h1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc27
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h7
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc39
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h16
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc245
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_operation.h1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_quota_client.h4
-rw-r--r--chromium/content/browser/child_process_launcher.cc50
-rw-r--r--chromium/content/browser/child_process_launcher.h5
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc59
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h26
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc4
-rw-r--r--chromium/content/browser/compositor/OWNERS4
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc2
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h16
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc78
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h38
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.mm1
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc67
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h6
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc10
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h3
-rw-r--r--chromium/content/browser/compositor/mus_browser_compositor_output_surface.cc89
-rw-r--r--chromium/content/browser/compositor/mus_browser_compositor_output_surface.h52
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc21
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h21
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc23
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc44
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.h17
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc7
-rw-r--r--chromium/content/browser/compositor/software_output_device_ozone.cc2
-rw-r--r--chromium/content/browser/compositor/software_output_device_win.cc4
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc76
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h31
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc2
-rw-r--r--chromium/content/browser/device_sensors/DEPS1
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory.h6
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc6
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc6
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc6
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc24
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_browsertest.cc154
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_host.cc8
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android.cc129
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android.h24
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc4
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_chromeos.h4
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc4
-rw-r--r--chromium/content/browser/devtools/BUILD.gn32
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc121
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h17
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host_impl.cc10
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.h4
-rw-r--r--chromium/content/browser/devtools/devtools_manager.cc26
-rw-r--r--chromium/content/browser/devtools/devtools_manager.h4
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc16
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_handler.h1
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc35
-rw-r--r--chromium/content/browser/devtools/devtools_session.h30
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.cc4
-rw-r--r--chromium/content/browser/devtools/page_navigation_throttle.cc10
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc170
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h78
-rw-r--r--chromium/content/browser/devtools/protocol/color_picker.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc264
-rwxr-xr-xchromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py54
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc34
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.h10
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc10
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.h10
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.cc13
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.h1
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc14
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h7
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc56
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h26
-rw-r--r--chromium/content/browser/devtools/protocol/schema_handler.cc4
-rw-r--r--chromium/content/browser/devtools/protocol/security_handler.cc16
-rw-r--r--chromium/content/browser/devtools/protocol/security_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc139
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h25
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.cc18
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.h2
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h1
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc2
-rw-r--r--chromium/content/browser/devtools/protocol_config.json30
-rw-r--r--chromium/content/browser/devtools/protocol_string.cc107
-rw-r--r--chromium/content/browser/devtools/protocol_string.h58
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc119
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h11
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc1
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.cc17
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc1
-rw-r--r--chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc2
-rw-r--r--chromium/content/browser/devtools/worker_devtools_agent_host.cc18
-rw-r--r--chromium/content/browser/devtools/worker_devtools_agent_host.h1
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc63
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.h7
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc106
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc37
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h6
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.cc5
-rw-r--r--chromium/content/browser/download/base_file.h1
-rw-r--r--chromium/content/browser/download/base_file_unittest.cc11
-rw-r--r--chromium/content/browser/download/download_file.h2
-rw-r--r--chromium/content/browser/download/download_file_factory.h5
-rw-r--r--chromium/content/browser/download/download_file_impl.h2
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc24
-rw-r--r--chromium/content/browser/download/download_item_impl.cc53
-rw-r--r--chromium/content/browser/download/download_item_impl.h3
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc290
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc70
-rw-r--r--chromium/content/browser/download/download_manager_impl.h3
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc5
-rw-r--r--chromium/content/browser/download/download_net_log_parameters.h2
-rw-r--r--chromium/content/browser/download/download_request_core.cc4
-rw-r--r--chromium/content/browser/download/download_request_core.h1
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc1
-rw-r--r--chromium/content/browser/download/download_resource_handler.h3
-rw-r--r--chromium/content/browser/download/drag_download_file.h1
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc13
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.h4
-rw-r--r--chromium/content/browser/download/mock_download_file.h1
-rw-r--r--chromium/content/browser/download/quarantine_mac.mm6
-rw-r--r--chromium/content/browser/download/save_file_manager.cc35
-rw-r--r--chromium/content/browser/download/save_file_manager.h9
-rw-r--r--chromium/content/browser/download/save_package.cc61
-rw-r--r--chromium/content/browser/download/save_package.h9
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.h1
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc4
-rw-r--r--chromium/content/browser/fileapi/fileapi_browsertest.cc53
-rw-r--r--chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc12
-rw-r--r--chromium/content/browser/find_request_manager_browsertest.cc5
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc49
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h24
-rw-r--r--chromium/content/browser/frame_host/cross_site_transferring_request.cc46
-rw-r--r--chromium/content/browser/frame_host/cross_site_transferring_request.h42
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc52
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc18
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h1
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc11
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc17
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc24
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h13
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc26
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.h18
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h10
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc108
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h28
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc360
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc370
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc31
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h4
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc12
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc238
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h77
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc88
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc31
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc82
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h2
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc8
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h9
-rw-r--r--chromium/content/browser/frame_host/navigator.cc5
-rw-r--r--chromium/content/browser/frame_host/navigator.h35
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.h1
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc103
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h29
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc34
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h27
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.cc9
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.h6
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc730
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h160
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc225
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h19
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc170
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc1
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc6
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc14
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.h2
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc66
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.h11
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc48
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h6
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc8
-rw-r--r--chromium/content/browser/gamepad/gamepad_service.h1
-rw-r--r--chromium/content/browser/generic_sensor_browsertest.cc136
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc12
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc8
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h2
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc20
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc45
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc57
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc61
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h7
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.h8
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.cc76
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.h81
-rw-r--r--chromium/content/browser/gpu/shader_disk_cache.cc325
-rw-r--r--chromium/content/browser/gpu/shader_disk_cache.h57
-rw-r--r--chromium/content/browser/gpu/shader_disk_cache_unittest.cc4
-rw-r--r--chromium/content/browser/histogram_synchronizer.cc47
-rw-r--r--chromium/content/browser/histogram_synchronizer.h36
-rw-r--r--chromium/content/browser/host_zoom_level_context.h2
-rw-r--r--chromium/content/browser/host_zoom_map_impl.h2
-rw-r--r--chromium/content/browser/host_zoom_map_observer.cc58
-rw-r--r--chromium/content/browser/host_zoom_map_observer.h31
-rw-r--r--chromium/content/browser/iframe_zoom_browsertest.cc2
-rw-r--r--chromium/content/browser/indexed_db/database_impl.cc781
-rw-r--r--chromium/content/browser/indexed_db/database_impl.h130
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc616
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h31
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.cc16
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc20
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc31
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h13
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc117
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.h18
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc20
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc808
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h175
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc9
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.cc28
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.h27
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.cc72
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.h83
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc13
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc2
-rw-r--r--chromium/content/browser/loader/DEPS8
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc17
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h3
-rw-r--r--chromium/content/browser/loader/async_resource_handler_browsertest.cc4
-rw-r--r--chromium/content/browser/loader/async_resource_handler_unittest.cc13
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver.h4
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager.cc4
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_browsertest.cc28
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_unittest.cc3
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.cc388
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.h97
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc3
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.cc287
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.h91
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler_unittest.cc584
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc172
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc122
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h26
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc155
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.cc83
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.h11
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h1
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc3
-rw-r--r--chromium/content/browser/loader/reload_cache_control_browsertest.cc20
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc61
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc352
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h86
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc267
-rw-r--r--chromium/content/browser/loader/resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/resource_handler.h7
-rw-r--r--chromium/content/browser/loader/resource_loader.cc38
-rw-r--r--chromium/content/browser/loader/resource_loader.h10
-rw-r--r--chromium/content/browser/loader/resource_loader_delegate.h2
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc44
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h26
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc11
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h26
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc78
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h5
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc120
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.cc24
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.h11
-rw-r--r--chromium/content/browser/loader/test_resource_handler.cc111
-rw-r--r--chromium/content/browser/loader/test_resource_handler.h132
-rw-r--r--chromium/content/browser/loader/test_url_loader_client.cc59
-rw-r--r--chromium/content/browser/loader/test_url_loader_client.h38
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc5
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl.cc64
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl.h29
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc190
-rw-r--r--chromium/content/browser/manifest/manifest_browsertest.cc14
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.cc18
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.h6
-rw-r--r--chromium/content/browser/media/OWNERS1
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc5
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h2
-rw-r--r--chromium/content/browser/media/android/browser_media_session_manager.cc36
-rw-r--r--chromium/content/browser/media/android/browser_media_session_manager.h36
-rw-r--r--chromium/content/browser/media/android/browser_media_session_manager_browsertest.cc248
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.cc26
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.h6
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.cc76
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.h7
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.h4
-rw-r--r--chromium/content/browser/media/android/media_session_service_impl.cc48
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.cc24
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.h16
-rw-r--r--chromium/content/browser/media/android/provision_fetcher_impl.cc56
-rw-r--r--chromium/content/browser/media/android/provision_fetcher_impl.h51
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc63
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.h25
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc13
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.cc16
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.h2
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.cc5
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc87
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.h1
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.h4
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc19
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc14
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android.h4
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc99
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc15
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.h3
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc111
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.h3
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc30
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc58
-rw-r--r--chromium/content/browser/media/media_browsertest.cc7
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc39
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker.cc153
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker.h92
-rw-r--r--chromium/content/browser/media/media_internals.cc57
-rw-r--r--chromium/content/browser/media/media_internals.h3
-rw-r--r--chromium/content/browser/media/media_redirect_browsertest.cc3
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc41
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h1
-rw-r--r--chromium/content/browser/media/midi_host.cc79
-rw-r--r--chromium/content/browser/media/midi_host.h33
-rw-r--r--chromium/content/browser/media/midi_host_unittest.cc88
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate.h31
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.cc102
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.h (renamed from chromium/content/browser/media/session/media_session_delegate_android.h)22
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android_browsertest.cc (renamed from chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc)26
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default.cc (renamed from chromium/content/browser/media/session/media_session_delegate_default.cc)39
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc (renamed from chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc)33
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.cc23
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.h10
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager_unittest.cc105
-rw-r--r--chromium/content/browser/media/session/media_metadata_sanitizer.cc111
-rw-r--r--chromium/content/browser/media/session/media_metadata_sanitizer.h23
-rw-r--r--chromium/content/browser/media/session/media_session_android.cc172
-rw-r--r--chromium/content/browser/media/session/media_session_android.h69
-rw-r--r--chromium/content/browser/media/session/media_session_browsertest.cc1347
-rw-r--r--chromium/content/browser/media/session/media_session_controller.cc5
-rw-r--r--chromium/content/browser/media/session/media_session_controller.h10
-rw-r--r--chromium/content/browser/media/session/media_session_controller_unittest.cc6
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.cc2
-rw-r--r--chromium/content/browser/media/session/media_session_delegate.h30
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_android.cc101
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc (renamed from chromium/content/browser/media/session/media_session.cc)313
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h (renamed from chromium/content/browser/media/session/media_session.h)167
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc1316
-rw-r--r--chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc (renamed from chromium/content/browser/media/session/media_session_visibility_browsertest.cc)123
-rw-r--r--chromium/content/browser/media/session/media_session_player_observer.h (renamed from chromium/content/browser/media/session/media_session_observer.h)12
-rw-r--r--chromium/content/browser/media/session/media_session_service_impl.cc89
-rw-r--r--chromium/content/browser/media/session/media_session_service_impl.h (renamed from chromium/content/browser/media/android/media_session_service_impl.h)24
-rw-r--r--chromium/content/browser/media/session/mock_media_session_player_observer.cc (renamed from chromium/content/browser/media/session/mock_media_session_observer.cc)28
-rw-r--r--chromium/content/browser/media/session/mock_media_session_player_observer.h (renamed from chromium/content/browser/media/session/mock_media_session_observer.h)17
-rw-r--r--chromium/content/browser/media/session/pepper_playback_observer.cc28
-rw-r--r--chromium/content/browser/media/session/pepper_playback_observer.h2
-rw-r--r--chromium/content/browser/media/session/pepper_player_delegate.cc16
-rw-r--r--chromium/content/browser/media/session/pepper_player_delegate.h8
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.cc (renamed from chromium/content/browser/media/android/url_provision_fetcher.cc)5
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.h (renamed from chromium/content/browser/media/android/url_provision_fetcher.h)8
-rw-r--r--chromium/content/browser/memory/memory_coordinator.cc119
-rw-r--r--chromium/content/browser/memory/memory_coordinator.h44
-rw-r--r--chromium/content/browser/memory/memory_coordinator_browsertest.cc26
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl.cc330
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl.h137
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl_unittest.cc219
-rw-r--r--chromium/content/browser/memory/memory_coordinator_unittest.cc16
-rw-r--r--chromium/content/browser/memory/memory_monitor.cc8
-rw-r--r--chromium/content/browser/memory/memory_monitor_android.cc39
-rw-r--r--chromium/content/browser/memory/memory_monitor_linux.cc8
-rw-r--r--chromium/content/browser/memory/memory_monitor_linux_unittest.cc2
-rw-r--r--chromium/content/browser/memory/memory_pressure_controller_impl.cc3
-rw-r--r--chromium/content/browser/message_port_provider.cc76
-rw-r--r--chromium/content/browser/message_port_provider_browsertest.cc55
-rw-r--r--chromium/content/browser/mojo_sandbox_browsertest.cc2
-rw-r--r--chromium/content/browser/net/browser_online_state_observer.cc8
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc6
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.h8
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store_unittest.cc36
-rw-r--r--chromium/content/browser/net/view_blob_internals_job_factory.cc2
-rw-r--r--chromium/content/browser/net/view_http_cache_job_factory.cc2
-rw-r--r--chromium/content/browser/notification_service_impl.cc20
-rw-r--r--chromium/content/browser/notifications/notification_database.h1
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc9
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.h1
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.cc6
-rw-r--r--chromium/content/browser/payments/OWNERS2
-rw-r--r--chromium/content/browser/payments/payment_app_context.cc68
-rw-r--r--chromium/content/browser/payments/payment_app_context.h62
-rw-r--r--chromium/content/browser/payments/payment_app_manager.cc45
-rw-r--r--chromium/content/browser/payments/payment_app_manager.h50
-rw-r--r--chromium/content/browser/pepper_flash_settings_helper_impl.cc2
-rw-r--r--chromium/content/browser/permissions/permission_service_context.cc85
-rw-r--r--chromium/content/browser/permissions/permission_service_context.h22
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc85
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.h32
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc2
-rw-r--r--chromium/content/browser/plugin_service_impl.cc2
-rw-r--r--chromium/content/browser/plugin_service_impl.h1
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.cc46
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.h41
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster_unittest.cc116
-rw-r--r--chromium/content/browser/power_usage_monitor_impl.cc278
-rw-r--r--chromium/content/browser/power_usage_monitor_impl.h133
-rw-r--r--chromium/content/browser/power_usage_monitor_impl_unittest.cc169
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc59
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc71
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h20
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc185
-rw-r--r--chromium/content/browser/presentation/presentation_type_converters.h6
-rw-r--r--chromium/content/browser/presentation/presentation_type_converters_unittest.cc4
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_message_filter.cc6
-rw-r--r--chromium/content/browser/quota/quota_manager_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/DEPS9
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h2
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm5
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.h4
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc159
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h14
-rw-r--r--chromium/content/browser/renderer_host/context_provider_factory_impl_android.cc5
-rw-r--r--chromium/content/browser/renderer_host/context_provider_factory_impl_android.h5
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc9
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc69
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h24
-rw-r--r--chromium/content/browser/renderer_host/gamepad_browser_message_filter.h8
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc6
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.h1
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h3
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/input_ack_handler.h2
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h4
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h7
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h5
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h5
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.h2
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h6
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h2
-rw-r--r--chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc145
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc163
-rw-r--r--chromium/content/browser/renderer_host/input/stylus_text_selector.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h5
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc14
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_client.h3
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc22
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc2
-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/touchpad_tap_suppression_controller.h2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc37
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.h15
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h3
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm79
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc165
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer.h47
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc107
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc122
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h1
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc59
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h16
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc25
-rw-r--r--chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.cc44
-rw-r--r--chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.h38
-rw-r--r--chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.cc105
-rw-r--r--chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.h42
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc296
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h110
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc331
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc36
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.h35
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc125
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc139
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h43
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc107
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc354
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h64
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc129
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_requester.h8
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.cc13
-rw-r--r--chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.h3
-rw-r--r--chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.h6
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc107
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc66
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h12
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc146
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc335
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h137
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc568
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc40
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc21
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_unittest.cc367
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc68
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h8
-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.h7
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.cc53
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.h51
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc128
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h7
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc5
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h3
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc79
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h33
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc501
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h79
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.cc12
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h28
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate_view.h14
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.h2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc438
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h69
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc21
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h5
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc20
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h54
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc510
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h137
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc92
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h9
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc50
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc134
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h23
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc881
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h159
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc146
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc30
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h52
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc873
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h253
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h22
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm171
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm158
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.cc6
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.h7
-rw-r--r--chromium/content/browser/renderer_host/renderer_frame_manager.cc91
-rw-r--r--chromium/content/browser/renderer_host/renderer_frame_manager.h14
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.cc21
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.h1
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc2
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc62
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js1
-rw-r--r--chromium/content/browser/resources/media/cache_entry.js2
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js34
-rw-r--r--chromium/content/browser/resources/media/media_internals.html1
-rw-r--r--chromium/content/browser/resources/media/player_info.js7
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc3
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc11
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc6
-rw-r--r--chromium/content/browser/service_manager/OWNERS1
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc105
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.h6
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc174
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h16
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc157
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc6
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h7
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc192
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h85
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.cc25
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.h11
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc188
-rw-r--r--chromium/content/browser/service_worker/link_header_support.cc25
-rw-r--r--chromium/content/browser/service_worker/link_header_support_unittest.cc110
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc822
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc44
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_unittest.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc16
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc195
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc49
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.proto15
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc569
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h48
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc69
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc208
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h28
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle_unittest.cc31
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.cc49
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.h13
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc131
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc16
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h17
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc16
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc46
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h12
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_handle.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc63
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc283
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_unregister_job.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc220
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h17
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc135
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc155
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h91
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc166
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h9
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc29
-rw-r--r--chromium/content/browser/session_history_browsertest.cc5
-rw-r--r--chromium/content/browser/shapedetection/shapedetection_browsertest.cc89
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc11
-rw-r--r--chromium/content/browser/site_instance_impl.cc16
-rw-r--r--chromium/content/browser/site_instance_impl.h5
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc14
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc604
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.h2
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc141
-rw-r--r--chromium/content/browser/ssl/ssl_manager.h42
-rw-r--r--chromium/content/browser/ssl/ssl_manager_unittest.cc106
-rw-r--r--chromium/content/browser/storage_partition_impl.cc16
-rw-r--r--chromium/content/browser/storage_partition_impl.h4
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc3
-rw-r--r--chromium/content/browser/theme_helper_mac.mm34
-rw-r--r--chromium/content/browser/top_document_isolation_browsertest.cc79
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h1
-rw-r--r--chromium/content/browser/tracing/memory_tracing_browsertest.cc7
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc5
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.h2
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc15
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc60
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h15
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc5
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc35
-rw-r--r--chromium/content/browser/utility_process_host_impl.h2
-rw-r--r--chromium/content/browser/utility_process_host_impl_browsertest.cc4
-rw-r--r--chromium/content/browser/vibration_browsertest.cc2
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_browsertest.cc4
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.cc82
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.h69
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context_unittest.cc63
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_impl.cc37
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_impl.h35
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.cc4
-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.cc6
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_animation.h2
-rw-r--r--chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc5
-rw-r--r--chromium/content/browser/web_contents/aura/shadow_layer_delegate.h5
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc85
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h48
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc872
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h167
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc78
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc307
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc87
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h20
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc145
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h42
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc8
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.h3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm41
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mus.cc5
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mus.h4
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.h31
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm147
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.h6
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm52
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm1
-rw-r--r--chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc77
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc61
-rw-r--r--chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc132
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.cc39
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.h25
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_message_handler.cc2
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_message_handler.h6
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_ui_observer.h2
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_unittest.cc58
-rw-r--r--chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc46
-rw-r--r--chromium/content/browser/websockets/websocket_handshake_request_info_impl.h38
-rw-r--r--chromium/content/browser/websockets/websocket_impl.cc19
-rw-r--r--chromium/content/browser/websockets/websocket_impl.h2
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc57
-rw-r--r--chromium/content/browser/websockets/websocket_manager.h15
-rw-r--r--chromium/content/browser/websockets/websocket_manager_unittest.cc12
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.cc36
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc3
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.h4
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc34
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc19
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h8
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_unittest.cc12
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc22
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h13
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc6
896 files changed, 31958 insertions, 21563 deletions
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 21b62d48a09..660a42da03a 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -5,6 +5,8 @@
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//media/media_options.gni")
+import("//printing/features/features.gni")
+import("//third_party/WebKit/public/public_features.gni")
import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
source_set("browser") {
@@ -22,7 +24,6 @@ source_set("browser") {
configs += [
"//build/config:precompiled_headers",
"//content:content_implementation",
- "//third_party/WebKit/public:debug_devtools",
"//v8:external_startup_data",
]
defines = []
@@ -35,20 +36,25 @@ source_set("browser") {
"//base/third_party/dynamic_annotations",
"//cc",
"//cc/surfaces",
+ "//components/discardable_memory/common",
+ "//components/discardable_memory/service",
"//components/display_compositor",
"//components/filesystem:lib",
"//components/leveldb:lib",
"//components/link_header_util",
"//components/mime_util",
+ "//components/payments:payment_app",
"//components/tracing",
"//components/tracing:startup_tracing",
"//components/url_formatter",
+ "//components/variations",
"//content:resources",
"//content/app/resources",
"//content/app/strings",
"//content/browser/background_sync:background_sync_proto",
"//content/browser/cache_storage:cache_storage_proto",
"//content/browser/devtools:gen_devtools_protocol_handler",
+ "//content/browser/devtools:protocol_sources",
"//content/browser/devtools:resources",
"//content/browser/notifications:notification_proto",
"//content/browser/service_worker:service_worker_proto",
@@ -64,9 +70,13 @@ source_set("browser") {
"//device/geolocation",
"//device/geolocation/public/interfaces",
"//device/nfc:mojo_bindings",
+ "//device/power_monitor",
"//device/power_save_blocker",
+ "//device/sensors/public/cpp",
"//device/time_zone_monitor",
+ "//device/time_zone_monitor/public/interfaces",
"//device/vibration",
+ "//device/wake_lock",
"//gin",
"//google_apis",
"//gpu",
@@ -78,6 +88,7 @@ source_set("browser") {
"//media/capture",
"//media/gpu/ipc/client",
"//media/midi",
+ "//media/midi:mojo_cpp_sources",
"//media/mojo/interfaces",
"//media/mojo/interfaces:image_capture",
"//mojo/common",
@@ -87,19 +98,24 @@ source_set("browser") {
"//net",
"//net:extras",
"//net:http_server",
+ "//ppapi/features",
+ "//printing/features",
+ "//services/catalog/public/interfaces:constants",
+ "//services/device:lib",
+ "//services/device/public/cpp",
"//services/file:lib",
- "//services/file/public/cpp",
"//services/file/public/interfaces",
- "//services/shell",
- "//services/shell/public/cpp",
- "//services/shell/public/interfaces",
- "//services/shell/runner/common",
- "//services/shell/runner/host:lib",
+ "//services/service_manager",
+ "//services/service_manager/public/cpp",
+ "//services/service_manager/public/interfaces",
+ "//services/service_manager/runner/common",
+ "//services/service_manager/runner/host:lib",
"//skia",
"//sql",
"//storage/browser",
"//storage/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:offscreen_canvas_mojo_bindings",
@@ -128,11 +144,11 @@ source_set("browser") {
"//ui/resources",
"//ui/shell_dialogs",
"//ui/snapshot",
- "//ui/surface",
"//ui/touch_selection",
]
public_deps = [
+ "//media/mojo/interfaces:remoting",
"//third_party/leveldatabase",
]
@@ -141,6 +157,13 @@ source_set("browser") {
# //content/browser/devtools:gen_devtools_protocol_handler.
"$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.cc",
"$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.h",
+ "$target_gen_dir/devtools/protocol/forward.h",
+ "$target_gen_dir/devtools/protocol/io.cc",
+ "$target_gen_dir/devtools/protocol/io.h",
+ "$target_gen_dir/devtools/protocol/protocol.cc",
+ "$target_gen_dir/devtools/protocol/protocol.h",
+ "$target_gen_dir/devtools/protocol/tracing.cc",
+ "$target_gen_dir/devtools/protocol/tracing.h",
"../common/service_manager/child_connection.cc",
"../common/service_manager/child_connection.h",
"../zygote/zygote_linux.cc",
@@ -159,6 +182,8 @@ source_set("browser") {
"accessibility/accessibility_tree_formatter_win.cc",
"accessibility/accessibility_ui.cc",
"accessibility/accessibility_ui.h",
+ "accessibility/ax_platform_position.cc",
+ "accessibility/ax_platform_position.h",
"accessibility/ax_tree_id_registry.cc",
"accessibility/ax_tree_id_registry.h",
"accessibility/browser_accessibility.cc",
@@ -185,6 +210,10 @@ source_set("browser") {
"accessibility/browser_accessibility_win.h",
"accessibility/one_shot_accessibility_tree_search.cc",
"accessibility/one_shot_accessibility_tree_search.h",
+ "android/app_web_message_port_message_filter.cc",
+ "android/app_web_message_port_message_filter.h",
+ "android/app_web_message_port_service_impl.cc",
+ "android/app_web_message_port_service_impl.h",
"android/background_sync_network_observer_android.cc",
"android/background_sync_network_observer_android.h",
"android/browser_jni_registrar.cc",
@@ -278,8 +307,8 @@ source_set("browser") {
"blob_storage/chrome_blob_storage_context.h",
"bluetooth/bluetooth_allowed_devices_map.cc",
"bluetooth/bluetooth_allowed_devices_map.h",
- "bluetooth/bluetooth_blacklist.cc",
- "bluetooth/bluetooth_blacklist.h",
+ "bluetooth/bluetooth_blocklist.cc",
+ "bluetooth/bluetooth_blocklist.h",
"bluetooth/bluetooth_device_chooser_controller.cc",
"bluetooth/bluetooth_device_chooser_controller.h",
"bluetooth/bluetooth_metrics.cc",
@@ -395,12 +424,12 @@ source_set("browser") {
"devtools/devtools_manager.h",
"devtools/devtools_protocol_handler.cc",
"devtools/devtools_protocol_handler.h",
+ "devtools/devtools_session.cc",
+ "devtools/devtools_session.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/color_picker.cc",
"devtools/protocol/color_picker.h",
"devtools/protocol/devtools_protocol_client.cc",
@@ -438,6 +467,8 @@ source_set("browser") {
"devtools/protocol/tethering_handler.h",
"devtools/protocol/tracing_handler.cc",
"devtools/protocol/tracing_handler.h",
+ "devtools/protocol_string.cc",
+ "devtools/protocol_string.h",
"devtools/render_frame_devtools_agent_host.cc",
"devtools/render_frame_devtools_agent_host.h",
"devtools/service_worker_devtools_agent_host.cc",
@@ -547,8 +578,6 @@ source_set("browser") {
"font_list_async.cc",
"frame_host/cross_process_frame_connector.cc",
"frame_host/cross_process_frame_connector.h",
- "frame_host/cross_site_transferring_request.cc",
- "frame_host/cross_site_transferring_request.h",
"frame_host/debug_urls.cc",
"frame_host/debug_urls.h",
"frame_host/frame_navigation_entry.cc",
@@ -622,8 +651,6 @@ source_set("browser") {
"gpu/gpu_process_host.h",
"gpu/gpu_process_host_ui_shim.cc",
"gpu/gpu_process_host_ui_shim.h",
- "gpu/gpu_surface_tracker.cc",
- "gpu/gpu_surface_tracker.h",
"gpu/shader_disk_cache.cc",
"gpu/shader_disk_cache.h",
"histogram_controller.cc",
@@ -639,6 +666,10 @@ source_set("browser") {
"host_zoom_level_context.h",
"host_zoom_map_impl.cc",
"host_zoom_map_impl.h",
+ "host_zoom_map_observer.cc",
+ "host_zoom_map_observer.h",
+ "indexed_db/database_impl.cc",
+ "indexed_db/database_impl.h",
"indexed_db/indexed_db.h",
"indexed_db/indexed_db_active_blob_registry.cc",
"indexed_db/indexed_db_active_blob_registry.h",
@@ -674,8 +705,6 @@ source_set("browser") {
"indexed_db/indexed_db_internals_ui.h",
"indexed_db/indexed_db_leveldb_coding.cc",
"indexed_db/indexed_db_leveldb_coding.h",
- "indexed_db/indexed_db_metadata.cc",
- "indexed_db/indexed_db_metadata.h",
"indexed_db/indexed_db_observation.cc",
"indexed_db/indexed_db_observation.h",
"indexed_db/indexed_db_observer.cc",
@@ -714,8 +743,6 @@ source_set("browser") {
"loader/async_revalidation_driver.h",
"loader/async_revalidation_manager.cc",
"loader/async_revalidation_manager.h",
- "loader/cross_site_resource_handler.cc",
- "loader/cross_site_resource_handler.h",
"loader/detachable_resource_handler.cc",
"loader/detachable_resource_handler.h",
"loader/global_routing_id.h",
@@ -790,24 +817,16 @@ source_set("browser") {
"manifest/manifest_manager_host.h",
"media/android/browser_media_player_manager.cc",
"media/android/browser_media_player_manager.h",
- "media/android/browser_media_session_manager.cc",
- "media/android/browser_media_session_manager.h",
"media/android/browser_surface_view_manager.cc",
"media/android/browser_surface_view_manager.h",
"media/android/media_player_renderer.cc",
"media/android/media_player_renderer.h",
"media/android/media_resource_getter_impl.cc",
"media/android/media_resource_getter_impl.h",
- "media/android/media_session_service_impl.cc",
- "media/android/media_session_service_impl.h",
"media/android/media_throttler.cc",
"media/android/media_throttler.h",
"media/android/media_web_contents_observer_android.cc",
"media/android/media_web_contents_observer_android.h",
- "media/android/provision_fetcher_impl.cc",
- "media/android/provision_fetcher_impl.h",
- "media/android/url_provision_fetcher.cc",
- "media/android/url_provision_fetcher.h",
"media/audible_metrics.cc",
"media/audible_metrics.h",
"media/audio_stream_monitor.cc",
@@ -839,6 +858,8 @@ source_set("browser") {
"media/capture/window_activity_tracker_mac.mm",
"media/cdm_service_impl.cc",
"media/cdm_service_impl.h",
+ "media/media_devices_permission_checker.cc",
+ "media/media_devices_permission_checker.h",
"media/media_internals.cc",
"media/media_internals.h",
"media/media_internals_handler.cc",
@@ -851,23 +872,33 @@ source_set("browser") {
"media/media_web_contents_observer.h",
"media/midi_host.cc",
"media/midi_host.h",
+ "media/session/audio_focus_delegate.h",
+ "media/session/audio_focus_delegate_android.cc",
+ "media/session/audio_focus_delegate_android.h",
+ "media/session/audio_focus_delegate_default.cc",
"media/session/audio_focus_manager.cc",
"media/session/audio_focus_manager.h",
- "media/session/media_session.cc",
- "media/session/media_session.h",
+ "media/session/media_metadata_sanitizer.cc",
+ "media/session/media_metadata_sanitizer.h",
+ "media/session/media_session_android.cc",
+ "media/session/media_session_android.h",
"media/session/media_session_controller.cc",
"media/session/media_session_controller.h",
"media/session/media_session_controllers_manager.cc",
"media/session/media_session_controllers_manager.h",
- "media/session/media_session_delegate.h",
- "media/session/media_session_delegate_android.cc",
- "media/session/media_session_delegate_android.h",
- "media/session/media_session_delegate_default.cc",
- "media/session/media_session_observer.h",
+ "media/session/media_session_impl.cc",
+ "media/session/media_session_impl.h",
+ "media/session/media_session_player_observer.h",
+ "media/session/media_session_service_impl.cc",
+ "media/session/media_session_service_impl.h",
"media/session/media_session_uma_helper.cc",
"media/session/media_session_uma_helper.h",
+ "media/url_provision_fetcher.cc",
+ "media/url_provision_fetcher.h",
"memory/memory_coordinator.cc",
"memory/memory_coordinator.h",
+ "memory/memory_coordinator_impl.cc",
+ "memory/memory_coordinator_impl.h",
"memory/memory_message_filter.cc",
"memory/memory_message_filter.h",
"memory/memory_monitor.cc",
@@ -915,14 +946,14 @@ source_set("browser") {
"notifications/platform_notification_context_impl.h",
"notifications/type_converters.cc",
"notifications/type_converters.h",
+ "payments/payment_app_context.cc",
+ "payments/payment_app_context.h",
+ "payments/payment_app_manager.cc",
+ "payments/payment_app_manager.h",
"permissions/permission_service_context.cc",
"permissions/permission_service_context.h",
"permissions/permission_service_impl.cc",
"permissions/permission_service_impl.h",
- "power_monitor_message_broadcaster.cc",
- "power_monitor_message_broadcaster.h",
- "power_usage_monitor_impl.cc",
- "power_usage_monitor_impl.h",
"presentation/presentation_service_impl.cc",
"presentation/presentation_service_impl.h",
"presentation/presentation_type_converters.cc",
@@ -1047,12 +1078,10 @@ source_set("browser") {
"renderer_host/media/audio_renderer_host.h",
"renderer_host/media/audio_sync_reader.cc",
"renderer_host/media/audio_sync_reader.h",
- "renderer_host/media/gpu_memory_buffer_handle.cc",
- "renderer_host/media/gpu_memory_buffer_handle.h",
- "renderer_host/media/gpu_memory_buffer_tracker.cc",
- "renderer_host/media/gpu_memory_buffer_tracker.h",
"renderer_host/media/media_capture_devices_impl.cc",
"renderer_host/media/media_capture_devices_impl.h",
+ "renderer_host/media/media_devices_dispatcher_host.cc",
+ "renderer_host/media/media_devices_dispatcher_host.h",
"renderer_host/media/media_devices_manager.cc",
"renderer_host/media/media_devices_manager.h",
"renderer_host/media/media_stream_dispatcher_host.cc",
@@ -1088,6 +1117,8 @@ source_set("browser") {
"renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.h",
"renderer_host/offscreen_canvas_surface_impl.cc",
"renderer_host/offscreen_canvas_surface_impl.h",
+ "renderer_host/offscreen_canvas_surface_manager.cc",
+ "renderer_host/offscreen_canvas_surface_manager.h",
"renderer_host/overscroll_configuration.cc",
"renderer_host/overscroll_controller.cc",
"renderer_host/overscroll_controller.h",
@@ -1321,10 +1352,6 @@ source_set("browser") {
"user_metrics.cc",
"utility_process_host_impl.cc",
"utility_process_host_impl.h",
- "wake_lock/wake_lock_service_context.cc",
- "wake_lock/wake_lock_service_context.h",
- "wake_lock/wake_lock_service_impl.cc",
- "wake_lock/wake_lock_service_impl.h",
"web_contents/aura/gesture_nav_simple.cc",
"web_contents/aura/gesture_nav_simple.h",
"web_contents/aura/overscroll_navigation_overlay.cc",
@@ -1352,6 +1379,8 @@ source_set("browser") {
"web_contents/web_drag_source_mac.mm",
"web_contents/web_drag_utils_win.cc",
"web_contents/web_drag_utils_win.h",
+ "websockets/websocket_handshake_request_info_impl.cc",
+ "websockets/websocket_handshake_request_info_impl.h",
"websockets/websocket_impl.cc",
"websockets/websocket_impl.h",
"websockets/websocket_manager.cc",
@@ -1454,7 +1483,6 @@ source_set("browser") {
deps += [
"//jingle:jingle_glue",
"//third_party/libjingle:libjingle_webrtc",
- "//third_party/webrtc",
"//third_party/webrtc/base:rtc_base",
"//third_party/webrtc/media:rtc_media",
"//third_party/webrtc/modules/desktop_capture:primitives",
@@ -1687,10 +1715,10 @@ source_set("browser") {
"android/load_url_params.h",
"android/overscroll_controller_android.cc",
"android/overscroll_controller_android.h",
+ "android/synchronous_compositor_browser_filter.cc",
+ "android/synchronous_compositor_browser_filter.h",
"android/synchronous_compositor_host.cc",
"android/synchronous_compositor_host.h",
- "android/synchronous_compositor_observer.cc",
- "android/synchronous_compositor_observer.h",
"android/tracing_controller_android.cc",
"android/tracing_controller_android.h",
"android/web_contents_observer_proxy.cc",
@@ -1720,11 +1748,9 @@ source_set("browser") {
sources -= [
"browser_ipc_logging.cc",
"device_sensors/data_fetcher_shared_memory_default.cc",
+ "media/session/audio_focus_delegate_default.cc",
"media/session/audio_focus_manager.cc",
"media/session/audio_focus_manager.h",
- "media/session/media_session_delegate_default.cc",
- "power_usage_monitor_impl.cc",
- "power_usage_monitor_impl.h",
"tracing/tracing_ui.cc",
"tracing/tracing_ui.h",
@@ -1752,7 +1778,6 @@ source_set("browser") {
"//media",
"//media/capture/content/android",
"//media/capture/video/android",
- "//media/mojo/interfaces",
"//mojo/android:libsystem_java",
"//ui/android",
]
@@ -1784,6 +1809,10 @@ source_set("browser") {
]
}
+ if (enable_mojo_media) {
+ deps += [ "//media/mojo/interfaces" ]
+ }
+
if (use_aura) {
deps += [
"//services/ui/public/cpp",
@@ -1796,6 +1825,8 @@ source_set("browser") {
sources += [
"compositor/mus_browser_compositor_output_surface.cc",
"compositor/mus_browser_compositor_output_surface.h",
+ "renderer_host/render_widget_host_view_event_handler.cc",
+ "renderer_host/render_widget_host_view_event_handler.h",
"renderer_host/render_widget_host_view_mus.cc",
"renderer_host/render_widget_host_view_mus.h",
"web_contents/web_contents_view_mus.cc",
@@ -1915,15 +1946,10 @@ source_set("browser") {
deps += [ "//ui/ozone" ]
}
- if (!is_mac && !is_android) {
- sources -= [
- "gpu/gpu_surface_tracker.cc",
- "gpu/gpu_surface_tracker.h",
- ]
- }
-
if (enable_webvr) {
deps += [ "//device/vr" ]
+ } else {
+ deps += [ "//device/vr:mojo_bindings" ]
}
if (enable_ipc_fuzzer) {
@@ -1935,7 +1961,6 @@ source_set("browser") {
"hyphenation/hyphenation_impl.cc",
"hyphenation/hyphenation_impl.h",
]
- defines += [ "USE_MINIKIN_HYPHENATION=1" ]
}
}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index d250d95544e..67c21058b88 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -1,10 +1,13 @@
include_rules = [
# Allow inclusion of specific components that we depend on.
# See comment in content/DEPS for which components are allowed.
+ "+components/discardable_memory/common",
+ "+components/discardable_memory/service",
"+components/filesystem",
"+components/leveldb",
"+components/link_header_util",
"+components/mime_util",
+ "+components/payments",
"+components/profile_service",
"+components/scheduler/common",
"+components/tracing",
@@ -17,11 +20,13 @@ include_rules = [
"+device/generic_sensor", # For sensors service.
"+device/geolocation",
"+device/nfc",
+ "+device/power_monitor",
"+device/power_save_blocker",
"+device/sensors/public",
"+device/time_zone_monitor", # For TimeZoneMonitor creation.
"+device/vibration", # For Vibration API
"+device/vr", # For WebVR API
+ "+device/wake_lock",
"+gin/v8_initializer.h",
"+mojo",
"+services",
@@ -58,11 +63,15 @@ include_rules = [
"+third_party/WebKit/public/platform/WebFocusType.h",
"+third_party/WebKit/public/platform/WebGamepad.h",
"+third_party/WebKit/public/platform/WebGamepads.h",
+ "+third_party/WebKit/public/platform/WebGestureEvent.h",
+ "+third_party/WebKit/public/platform/WebInputEvent.h",
"+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
"+third_party/WebKit/public/platform/WebNavigationHintType.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
+ "+third_party/WebKit/public/platform/WebSecurityStyle.h",
"+third_party/WebKit/public/platform/WebString.h",
+ "+third_party/WebKit/public/platform/WebTextInputType.h",
"+third_party/WebKit/public/platform/mime_registry.mojom.h",
"+third_party/WebKit/public/platform/modules/background_sync/background_sync.mojom.h",
"+third_party/WebKit/public/platform/modules/broadcastchannel/broadcast_channel.mojom.h",
@@ -88,8 +97,8 @@ include_rules = [
"+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerState.h",
"+third_party/WebKit/public/platform/modules/serviceworker/service_worker_event_status.mojom.h",
"+third_party/WebKit/public/platform/modules/vr/WebVR.h",
- "+third_party/WebKit/public/platform/modules/wake_lock/wake_lock_service.mojom.h",
"+third_party/WebKit/public/platform/modules/websockets/websocket.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",
@@ -98,7 +107,6 @@ include_rules = [
"+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/WebInputEvent.h",
"+third_party/WebKit/public/web/WebMediaPlayerAction.h",
"+third_party/WebKit/public/web/WebPluginAction.h",
"+third_party/WebKit/public/web/WebPopupType.h",
@@ -107,7 +115,6 @@ include_rules = [
"+third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h",
"+third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h",
"+third_party/WebKit/public/web/WebTextDirection.h",
- "+third_party/WebKit/public/web/WebTextInputType.h",
"+third_party/WebKit/public/web/WebTreeScopeType.h",
"+third_party/WebKit/public/web/mac/WebScrollbarTheme.h",
@@ -115,6 +122,7 @@ include_rules = [
# one separately.
"+third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h",
"+third_party/WebKit/public/platform/modules/notifications/notification_service.mojom.h",
+ "+third_party/WebKit/public/platform/modules/shapedetection/shapedetection.mojom.h",
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
new file mode 100644
index 00000000000..b649fc212a1
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -0,0 +1,133 @@
+// 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 "base/logging.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.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"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class AccessibilityActionBrowserTest : public ContentBrowserTest {
+ public:
+ AccessibilityActionBrowserTest() {}
+ ~AccessibilityActionBrowserTest() override {}
+
+ protected:
+ BrowserAccessibility* FindNode(ui::AXRole role,
+ const std::string& name) {
+ BrowserAccessibility* root = GetManager()->GetRoot();
+ CHECK(root);
+ return FindNodeInSubtree(*root, role, name);
+ }
+
+ BrowserAccessibilityManager* GetManager() {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ return web_contents->GetRootBrowserAccessibilityManager();
+ }
+
+ private:
+ BrowserAccessibility* FindNodeInSubtree(
+ BrowserAccessibility& node,
+ ui::AXRole role,
+ const std::string& name) {
+ if (node.GetRole() == role &&
+ node.GetStringAttribute(ui::AX_ATTR_NAME) == name)
+ return &node;
+ for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
+ BrowserAccessibility* result = FindNodeInSubtree(
+ *node.PlatformGetChild(i), role, name);
+ if (result)
+ return result;
+ }
+ return nullptr;
+ }
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, FocusAction) {
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ GURL url("data:text/html,"
+ "<button>One</button>"
+ "<button>Two</button>"
+ "<button>Three</button>");
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* target = FindNode(ui::AX_ROLE_BUTTON, "One");
+ ASSERT_NE(nullptr, target);
+
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_FOCUS);
+ GetManager()->SetFocus(*target);
+ waiter2.WaitForNotification();
+
+ BrowserAccessibility* focus = GetManager()->GetFocus();
+ EXPECT_EQ(focus->GetId(), target->GetId());
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
+ IncrementDecrementActions) {
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ GURL url("data:text/html,"
+ "<input type=range min=2 value=8 max=10 step=2>");
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* target = FindNode(ui::AX_ROLE_SLIDER, "");
+ ASSERT_NE(nullptr, target);
+ EXPECT_EQ(8.0, target->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE));
+
+ // Increment, should result in value changing from 8 to 10.
+ {
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_VALUE_CHANGED);
+ GetManager()->Increment(*target);
+ waiter2.WaitForNotification();
+ }
+ EXPECT_EQ(10.0, target->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE));
+
+ // Increment, should result in value staying the same (max).
+ {
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_VALUE_CHANGED);
+ GetManager()->Increment(*target);
+ waiter2.WaitForNotification();
+ }
+ EXPECT_EQ(10.0, target->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE));
+
+ // Decrement, should result in value changing from 10 to 8.
+ {
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_VALUE_CHANGED);
+ GetManager()->Decrement(*target);
+ waiter2.WaitForNotification();
+ }
+ EXPECT_EQ(8.0, target->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index cba1d0c2c18..7d9f0042da9 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -128,11 +128,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
const ui::AXNode* para = live_region->ChildAtIndex(0);
EXPECT_EQ(ui::AX_ROLE_PARAGRAPH, para->data().role);
- const ui::AXNode* button_container = root->ChildAtIndex(1);
- EXPECT_EQ(ui::AX_ROLE_GROUP, button_container->data().role);
- ASSERT_EQ(1, button_container->child_count());
-
- const ui::AXNode* button = button_container->ChildAtIndex(0);
+ const ui::AXNode* button = root->ChildAtIndex(1);
EXPECT_EQ(ui::AX_ROLE_BUTTON, button->data().role);
}
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
index c5c60391baf..1b67e306638 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -78,6 +78,12 @@ void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
if (line.find(base::ASCIIToUTF16(kSkipString)) != base::string16::npos)
return;
+ // Replace literal newlines with "<newline>"
+ base::ReplaceChars(line,
+ base::ASCIIToUTF16("\n"),
+ base::ASCIIToUTF16("<newline>"),
+ &line);
+
*contents += line + base::ASCIIToUTF16("\n");
if (line.find(base::ASCIIToUTF16(kSkipChildren)) != base::string16::npos)
return;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.h b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
index dc8961e5bf5..d9804ee2b92 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
@@ -19,8 +19,6 @@
namespace content {
-class WebContents;
-
// A utility class for formatting platform-specific accessibility information,
// for use in testing, debugging, and developer tools.
// This is extended by a subclass for each platform where accessibility is
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 2870e519a85..40bca53d0d0 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -35,6 +35,7 @@ const char* const BOOL_ATTRIBUTES[] = {
"editable_text",
"focusable",
"focused",
+ "has_non_empty_value",
"heading",
"hierarchical",
"invisible",
@@ -117,6 +118,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
dict->SetBoolean("editable_text", android_node->IsEditableText());
dict->SetBoolean("focusable", android_node->IsFocusable());
dict->SetBoolean("focused", android_node->IsFocused());
+ dict->SetBoolean("has_non_empty_value", android_node->HasNonEmptyValue());
dict->SetBoolean("heading", android_node->IsHeading());
dict->SetBoolean("hierarchical", android_node->IsHierarchical());
dict->SetBoolean("invisible", !android_node->IsVisibleToUser());
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index cf0db1142dd..20f041767ee 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -19,6 +19,7 @@
#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/webui/web_ui_data_source_impl.h"
#include "content/common/view_message_enums.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/favicon_status.h"
@@ -142,8 +143,8 @@ bool HandleRequestCallback(BrowserContext* current_context,
AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) {
// Set up the chrome://accessibility source.
- WebUIDataSource* html_source =
- WebUIDataSource::Create(kChromeUIAccessibilityHost);
+ WebUIDataSourceImpl* html_source = static_cast<WebUIDataSourceImpl*>(
+ WebUIDataSource::Create(kChromeUIAccessibilityHost));
web_ui->RegisterMessageCallback(
"toggleAccessibility",
@@ -170,6 +171,8 @@ AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) {
html_source->SetRequestFilter(
base::Bind(&HandleRequestCallback,
web_ui->GetWebContents()->GetBrowserContext()));
+ html_source->DisableI18nAndUseGzipForAllPaths();
+ html_source->ExcludePathFromGzip(kDataFile);
BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
index e03b7ae3f5e..9ece9acc367 100644
--- a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -72,8 +72,7 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_TREE_CHANGED);
- node->manager()->delegate()->AccessibilitySetAccessibilityFocus(
- node->GetId());
+ node->manager()->SetAccessibilityFocus(*node);
waiter.WaitForNotification();
int start_index = -1;
@@ -150,7 +149,9 @@ IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
GURL url("data:text/html,"
"<body>"
"<p>One, two, three!</p>"
+ "<p>"
"<button aria-label='Seven, eight, nine!'>Four, five, six!</button>"
+ "</p>"
"</body></html>");
BrowserAccessibility* root = LoadUrlAndGetAccessibilityRoot(url);
ASSERT_EQ(2U, root->PlatformChildCount());
@@ -176,7 +177,9 @@ IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
GURL url("data:text/html,"
"<body>"
"<p>One, two, three!</p>"
+ "<p>"
"<button aria-label='Seven, eight, nine!'>Four, five, six!</button>"
+ "</p>"
"</body></html>");
BrowserAccessibility* root = LoadUrlAndGetAccessibilityRoot(url);
ASSERT_EQ(2U, root->PlatformChildCount());
diff --git a/chromium/content/browser/accessibility/ax_platform_position.cc b/chromium/content/browser/accessibility/ax_platform_position.cc
new file mode 100644
index 00000000000..5ed4c8f0113
--- /dev/null
+++ b/chromium/content/browser/accessibility/ax_platform_position.cc
@@ -0,0 +1,93 @@
+// 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/accessibility/ax_platform_position.h"
+
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+
+namespace content {
+
+AXPlatformPosition::AXPlatformPosition() {}
+
+AXPlatformPosition::~AXPlatformPosition() {}
+
+void AXPlatformPosition::AnchorChild(int child_index,
+ AXTreeID* tree_id,
+ int32_t* child_id) const {
+ DCHECK(tree_id);
+ DCHECK(child_id);
+
+ if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
+ *tree_id = AXPosition::INVALID_TREE_ID;
+ *child_id = AXPosition::INVALID_ANCHOR_ID;
+ return;
+ }
+
+ BrowserAccessibility* child = nullptr;
+ if (GetAnchor()->PlatformIsLeaf()) {
+ child = GetAnchor()->InternalGetChild(child_index);
+ } else {
+ child = GetAnchor()->PlatformGetChild(child_index);
+ }
+ DCHECK(child);
+ *tree_id = child->manager()->ax_tree_id();
+ *child_id = child->GetId();
+}
+
+int AXPlatformPosition::AnchorChildCount() const {
+ if (!GetAnchor())
+ return 0;
+
+ if (GetAnchor()->PlatformIsLeaf()) {
+ return static_cast<int>(GetAnchor()->InternalChildCount());
+ } else {
+ return static_cast<int>(GetAnchor()->PlatformChildCount());
+ }
+}
+
+int AXPlatformPosition::AnchorIndexInParent() const {
+ return GetAnchor() ? static_cast<int>(GetAnchor()->GetIndexInParent())
+ : AXPosition::INVALID_INDEX;
+}
+
+void AXPlatformPosition::AnchorParent(AXTreeID* tree_id,
+ int32_t* parent_id) const {
+ DCHECK(tree_id);
+ DCHECK(parent_id);
+
+ if (!GetAnchor() || !GetAnchor()->GetParent()) {
+ *tree_id = AXPosition::INVALID_TREE_ID;
+ *parent_id = AXPosition::INVALID_ANCHOR_ID;
+ return;
+ }
+
+ BrowserAccessibility* parent = GetAnchor()->GetParent();
+ *tree_id = parent->manager()->ax_tree_id();
+ *parent_id = parent->GetId();
+}
+
+BrowserAccessibility* AXPlatformPosition::GetNodeInTree(AXTreeID tree_id,
+ int32_t node_id) const {
+ if (tree_id == AXPosition::INVALID_TREE_ID ||
+ node_id == AXPosition::INVALID_ANCHOR_ID) {
+ return nullptr;
+ }
+
+ auto manager = BrowserAccessibilityManager::FromID(tree_id);
+ if (!manager)
+ return nullptr;
+ return manager->GetFromID(node_id);
+}
+
+int AXPlatformPosition::MaxTextOffset() const {
+ if (IsNullPosition())
+ return AXPosition::INVALID_OFFSET;
+
+ BrowserAccessibility* anchor = GetNodeInTree(tree_id(), anchor_id());
+ if (!anchor)
+ return AXPosition::INVALID_OFFSET;
+ return static_cast<int>(anchor->GetText().length());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/ax_platform_position.h b/chromium/content/browser/accessibility/ax_platform_position.h
new file mode 100644
index 00000000000..f8b28e58ab9
--- /dev/null
+++ b/chromium/content/browser/accessibility/ax_platform_position.h
@@ -0,0 +1,38 @@
+// 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_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
+
+#include <stdint.h>
+
+#include "content/browser/accessibility/ax_tree_id_registry.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "ui/accessibility/ax_position.h"
+
+namespace content {
+
+using AXTreeID = content::AXTreeIDRegistry::AXTreeID;
+
+class AXPlatformPosition
+ : public ui::AXPosition<AXPlatformPosition, BrowserAccessibility> {
+ public:
+ AXPlatformPosition();
+ ~AXPlatformPosition() override;
+
+ protected:
+ void AnchorChild(int child_index,
+ AXTreeID* tree_id,
+ int32_t* child_id) const override;
+ int AnchorChildCount() const override;
+ int AnchorIndexInParent() const override;
+ void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override;
+ BrowserAccessibility* GetNodeInTree(AXTreeID tree_id,
+ int32_t node_id) const override;
+ int MaxTextOffset() const override;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index afcbd0036fb..f19ac2bd38c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -520,7 +520,9 @@ base::string16 BrowserAccessibility::GetValue() const {
// Some screen readers like Jaws and older versions of VoiceOver require a
// value to be set in text fields with rich content, even though the same
// information is available on the children.
- if (value.empty() && (IsSimpleTextControl() || IsRichTextControl()))
+ if (value.empty() &&
+ (IsSimpleTextControl() || IsRichTextControl()) &&
+ !IsNativeTextControl())
value = GetInnerText();
return value;
}
@@ -716,7 +718,7 @@ int BrowserAccessibility::GetWordStartBoundary(
}
}
-BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
+BrowserAccessibility* BrowserAccessibility::ApproximateHitTest(
const gfx::Point& point) {
// The best result found that's a child of this object.
BrowserAccessibility* child_result = NULL;
@@ -736,7 +738,7 @@ BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
continue;
if (child->GetScreenBoundsRect().Contains(point)) {
- BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point);
+ BrowserAccessibility* result = child->ApproximateHitTest(point);
if (result == child && !child_result)
child_result = result;
if (result != child && !descendant_result)
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index c9c577700cd..9311efc39c2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -48,11 +48,6 @@
namespace content {
class BrowserAccessibilityManager;
-#if defined(OS_WIN)
-class BrowserAccessibilityWin;
-#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11)
-class BrowserAccessibilityAuraLinux;
-#endif
////////////////////////////////////////////////////////////////////////////////
//
@@ -162,6 +157,12 @@ class CONTENT_EXPORT BrowserAccessibility {
// the role is WebAXRoleStaticText.
gfx::Rect GetScreenBoundsForRange(int start, int len) const;
+ // Convert a bounding rectangle from this node's coordinate system
+ // (which is relative to its nearest scrollable ancestor) to
+ // absolute bounds, either in page coordinates (when |frameOnly| is
+ // false), or in frame coordinates (when |frameOnly| is true).
+ gfx::Rect RelativeToAbsoluteBounds(gfx::RectF bounds, bool frame_only) const;
+
// This is to handle the cases such as ARIA textbox, where the value should
// be calculated from the object's inner text.
virtual base::string16 GetValue() const;
@@ -185,9 +186,13 @@ class CONTENT_EXPORT BrowserAccessibility {
int GetWordStartBoundary(int start,
ui::TextBoundaryDirection direction) const;
- // Returns the deepest descendant that contains the specified point
- // (in global screen coordinates).
- BrowserAccessibility* BrowserAccessibilityForPoint(const gfx::Point& point);
+ // This is an approximate hit test that only uses the information in
+ // the browser process to compute the correct result. It will not return
+ // correct results in many cases of z-index, overflow, and absolute
+ // positioning, so BrowserAccessibilityManager::CachingAsyncHitTest
+ // should be used instead, which falls back on calling ApproximateHitTest
+ // automatically.
+ BrowserAccessibility* ApproximateHitTest(const gfx::Point& screen_point);
// Marks this object for deletion, releases our reference to it, and
// nulls out the pointer to the underlying AXNode. May not delete
@@ -372,12 +377,6 @@ class CONTENT_EXPORT BrowserAccessibility {
// correspond to a layed-out element sometimes don't have bounds.
void FixEmptyBounds(gfx::RectF* bounds) const;
- // Convert the bounding rectangle of an element (which is relative to
- // its nearest scrollable ancestor) to absolute bounds, either in
- // page coordinates (when |frameOnly| is false), or in frame coordinates
- // (when |frameOnly| is true).
- gfx::Rect RelativeToAbsoluteBounds(gfx::RectF bounds, bool frame_only) const;
-
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 991cf010d1f..4c873c94eef 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -154,12 +154,14 @@ bool BrowserAccessibilityAndroid::IsChecked() const {
}
bool BrowserAccessibilityAndroid::IsClickable() const {
- if (!PlatformIsLeaf())
- return false;
+ // If it has a default action, it's definitely clickable.
+ if (HasStringAttribute(ui::AX_ATTR_ACTION))
+ return true;
- // We are very aggressive about returning true with IsClickable on Android
- // because there is no way to know for sure what might have a click handler.
- return IsFocusable() || !GetText().empty();
+ // Otherwise return true if it's focusable, but skip web areas and iframes.
+ if (IsIframe() || (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA))
+ return false;
+ return IsFocusable();
}
bool BrowserAccessibilityAndroid::IsCollapsed() const {
@@ -207,12 +209,14 @@ bool BrowserAccessibilityAndroid::IsExpanded() const {
}
bool BrowserAccessibilityAndroid::IsFocusable() const {
- bool focusable = HasState(ui::AX_STATE_FOCUSABLE);
- if (IsIframe() ||
- GetRole() == ui::AX_ROLE_WEB_AREA) {
- focusable = false;
- }
- return focusable;
+ // If it's an iframe element, or the root element of a child frame,
+ // only mark it as focusable if the element has an explicit name.
+ // Otherwise mark it as not focusable to avoid the user landing on
+ // empty container elements in the tree.
+ if (IsIframe() || (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA && GetParent()))
+ return HasStringAttribute(ui::AX_ATTR_NAME);
+
+ return HasState(ui::AX_STATE_FOCUSABLE);
}
bool BrowserAccessibilityAndroid::IsFocused() const {
@@ -273,6 +277,48 @@ bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
return !HasState(ui::AX_STATE_INVISIBLE);
}
+bool BrowserAccessibilityAndroid::IsInterestingOnAndroid() const {
+ // The root is not interesting if it doesn't have a title, even
+ // though it's focusable.
+ if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA && GetText().empty())
+ return false;
+
+ // Focusable nodes are always interesting. Note that IsFocusable()
+ // already skips over things like iframes and child frames that are
+ // technically focusable but shouldn't be exposed as focusable on Android.
+ if (IsFocusable())
+ return true;
+
+ // If it's not focusable but has a control role, then it's interesting.
+ if (IsControl())
+ return true;
+
+ // Otherwise, the interesting nodes are leaf nodes with non-whitespace text.
+ return PlatformIsLeaf() &&
+ !base::ContainsOnlyChars(GetText(), base::kWhitespaceUTF16);
+}
+
+const BrowserAccessibilityAndroid*
+ BrowserAccessibilityAndroid::GetSoleInterestingNodeFromSubtree() const {
+ if (IsInterestingOnAndroid())
+ return this;
+
+ const BrowserAccessibilityAndroid* sole_interesting_node = nullptr;
+ for (uint32_t i = 0; i < PlatformChildCount(); ++i) {
+ const BrowserAccessibilityAndroid* interesting_node =
+ static_cast<const BrowserAccessibilityAndroid*>(PlatformGetChild(i))->
+ GetSoleInterestingNodeFromSubtree();
+ if (interesting_node && sole_interesting_node) {
+ // If there are two interesting nodes, return nullptr.
+ return nullptr;
+ } else if (interesting_node) {
+ sole_interesting_node = interesting_node;
+ }
+ }
+
+ return sole_interesting_node;
+}
+
bool BrowserAccessibilityAndroid::CanOpenPopup() const {
return HasState(ui::AX_STATE_HASPOPUP);
}
@@ -412,6 +458,13 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
if (text.empty())
text = value;
+ // If this is the root element, give up now, allow it to have no
+ // accessible text. For almost all other focusable nodes we try to
+ // get text from contents, but for the root element that's redundant
+ // and often way too verbose.
+ if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA)
+ return text;
+
// This is called from PlatformIsLeaf, so don't call PlatformChildCount
// from within this!
if (text.empty() && (HasOnlyTextChildren() ||
@@ -1343,6 +1396,10 @@ bool BrowserAccessibilityAndroid::HasFocusableChild() const {
return false;
}
+bool BrowserAccessibilityAndroid::HasNonEmptyValue() const {
+ return IsEditableText() && !GetValue().empty();
+}
+
bool BrowserAccessibilityAndroid::HasOnlyTextChildren() const {
// This is called from PlatformIsLeaf, so don't call PlatformChildCount
// from within this!
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index f5e33a321bc..6942bb65644 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -48,9 +48,22 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool IsSlider() const;
bool IsVisibleToUser() const;
+ // This returns true for all nodes that we should navigate to.
+ // Nodes that have a generic role, no accessible name, and aren't
+ // focusable or clickable aren't interesting.
+ bool IsInterestingOnAndroid() const;
+
+ // If this node is interesting (IsInterestingOnAndroid() returns true),
+ // returns |this|. If not, it recursively checks all of the
+ // platform children of this node, and if just a single one is
+ // interesting, returns that one. If no descendants are interesting, or
+ // if more than one is interesting, returns nullptr.
+ const BrowserAccessibilityAndroid* GetSoleInterestingNodeFromSubtree() const;
+
bool CanOpenPopup() const;
bool HasFocusableChild() const;
+ bool HasNonEmptyValue() const;
const char* GetClassName() const;
base::string16 GetText() const override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
index c04a32e6044..1af9cccdc82 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -144,10 +144,7 @@ static AtkObject* browser_accessibility_accessible_at_point(
return NULL;
gfx::Point point(x, y);
- if (!obj->GetScreenBoundsRect().Contains(point))
- return NULL;
-
- BrowserAccessibility* result = obj->BrowserAccessibilityForPoint(point);
+ BrowserAccessibility* result = obj->manager()->CachingAsyncHitTest(point);
if (!result)
return NULL;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
index 773e79fbd31..b17cf0fb56d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
@@ -15,7 +15,6 @@
namespace content {
class BrowserAccessibilityAuraLinux;
-class BrowserAccessibilityManagerAuraLinux;
G_BEGIN_DECLS
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index cca823d03b6..140af1c12c1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -16,6 +16,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/app/strings/grit/content_strings.h"
+#include "content/browser/accessibility/ax_platform_position.h"
#include "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
@@ -24,6 +25,7 @@
#include "third_party/skia/include/core/SkColor.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
+using content::AXPlatformPosition;
using content::AXTreeIDRegistry;
using content::AccessibilityMatchPredicate;
using content::BrowserAccessibility;
@@ -94,13 +96,6 @@ NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible";
// A mapping from an accessibility attribute to its method name.
NSDictionary* attributeToMethodNameMap = nil;
-struct AXTextMarkerData {
- AXTreeIDRegistry::AXTreeID tree_id;
- int32_t node_id;
- int offset;
- ui::AXTextAffinity affinity;
-};
-
// VoiceOver uses -1 to mean "no limit" for AXResultsLimit.
const int kAXResultsLimitNoLimit = -1;
@@ -134,14 +129,16 @@ AXTextMarkerRef AXTextMarkerRangeCopyEndMarker(
id CreateTextMarker(const BrowserAccessibility& object,
int offset,
ui::AXTextAffinity affinity) {
- AXTextMarkerData marker_data;
- marker_data.tree_id = object.manager() ? object.manager()->ax_tree_id() : -1;
- marker_data.node_id = object.GetId();
- marker_data.offset = offset;
- marker_data.affinity = affinity;
+ if (!object.instance_active())
+ return nil;
+
+ const auto manager = object.manager();
+ DCHECK(manager);
+ auto marker_data = AXPlatformPosition::CreateTextPosition(
+ manager->ax_tree_id(), object.GetId(), offset, affinity);
return (id)base::mac::CFTypeRefToNSObjectAutorelease(AXTextMarkerCreate(
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&marker_data),
- sizeof(marker_data)));
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(marker_data),
+ sizeof(*marker_data)));
}
id CreateTextMarkerRange(const BrowserAccessibility& start_object,
@@ -163,26 +160,20 @@ bool GetTextMarkerData(AXTextMarkerRef text_marker,
ui::AXTextAffinity* affinity) {
DCHECK(text_marker);
DCHECK(object && offset);
- const auto* marker_data = reinterpret_cast<const AXTextMarkerData*>(
+ const auto* marker_data = reinterpret_cast<const AXPlatformPosition*>(
AXTextMarkerGetBytePtr(text_marker));
if (!marker_data)
return false;
- const BrowserAccessibilityManager* manager =
- BrowserAccessibilityManager::FromID(marker_data->tree_id);
- if (!manager)
- return false;
-
- *object = manager->GetFromID(marker_data->node_id);
+ *object = marker_data->GetAnchor();
if (!*object)
return false;
- *offset = marker_data->offset;
+ *offset = marker_data->text_offset();
if (*offset < 0)
return false;
- *affinity = marker_data->affinity;
-
+ *affinity = marker_data->affinity();
return true;
}
@@ -2796,15 +2787,18 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
return;
// TODO(dmazzoni): Support more actions.
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
if ([action isEqualToString:NSAccessibilityPressAction]) {
- [self delegate]->AccessibilityDoDefaultAction(
- browserAccessibility_->GetId());
+ manager->DoDefaultAction(*browserAccessibility_);
} else if ([action isEqualToString:NSAccessibilityShowMenuAction]) {
- [self delegate]->AccessibilityShowContextMenu(
- browserAccessibility_->GetId());
+ manager->ShowContextMenu(*browserAccessibility_);
} else if ([action isEqualToString:NSAccessibilityScrollToVisibleAction]) {
- browserAccessibility_->manager()->ScrollToMakeVisible(
+ manager->ScrollToMakeVisible(
*browserAccessibility_, gfx::Rect());
+ } else if ([action isEqualToString:NSAccessibilityIncrementAction]) {
+ manager->Increment(*browserAccessibility_);
+ } else if ([action isEqualToString:NSAccessibilityDecrementAction]) {
+ manager->Decrement(*browserAccessibility_);
}
}
@@ -2839,9 +2833,9 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
NSRange range = [(NSValue*)value rangeValue];
- [self delegate]->AccessibilitySetSelection(
- browserAccessibility_->GetId(), range.location,
- browserAccessibility_->GetId(), range.location + range.length);
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ manager->SetTextSelection(
+ *browserAccessibility_, range.location, range.location + range.length);
}
}
@@ -2853,25 +2847,15 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
if (![self instanceActive])
return nil;
- BrowserAccessibilityCocoa* hit = self;
- for (BrowserAccessibilityCocoa* child in [self children]) {
- if (!child->browserAccessibility_)
- continue;
- NSPoint origin = [child origin];
- NSSize size = [[child size] sizeValue];
- NSRect rect;
- rect.origin = origin;
- rect.size = size;
- if (NSPointInRect(point, rect)) {
- hit = child;
- id childResult = [child accessibilityHitTest:point];
- if (![childResult accessibilityIsIgnored]) {
- hit = childResult;
- break;
- }
- }
- }
- return NSAccessibilityUnignoredAncestor(hit);
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ gfx::Point screen_point(point.x, point.y);
+ screen_point += manager->GetViewBounds().OffsetFromOrigin();
+
+ BrowserAccessibility* hit = manager->CachingAsyncHitTest(screen_point);
+ if (!hit)
+ return nil;
+
+ return NSAccessibilityUnignoredAncestor(ToBrowserAccessibilityCocoa(hit));
}
- (BOOL)isEqual:(id)object {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 1a7a340fd76..cc23ee45d48 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -398,6 +398,9 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Fire the native event.
BrowserAccessibility* event_target = GetFromAXNode(node);
if (event_target) {
+ if (event_type == ui::AX_EVENT_HOVER)
+ GetRootManager()->CacheHitTestResult(event_target);
+
NotifyAccessibilityEvent(
BrowserAccessibilityEvent::FromBlink,
event_type,
@@ -456,7 +459,10 @@ void BrowserAccessibilityManager::OnChildFrameHitTestResult(
if (!child_manager || !child_manager->delegate())
return;
- return child_manager->delegate()->AccessibilityHitTest(point);
+ ui::AXActionData action_data;
+ action_data.target_point = point;
+ action_data.action = ui::AX_ACTION_HIT_TEST;
+ return child_manager->delegate()->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::ActivateFindInPageResult(
@@ -554,8 +560,13 @@ BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() {
}
void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
- if (delegate_)
- delegate_->AccessibilitySetFocus(node.GetId());
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_SET_FOCUS;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::SetFocusLocallyForTesting(
@@ -571,48 +582,134 @@ void BrowserAccessibilityManager::SetFocusChangeCallbackForTesting(
g_focus_change_callback_for_testing.Get() = callback;
}
+void BrowserAccessibilityManager::Decrement(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_DECREMENT;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
void BrowserAccessibilityManager::DoDefaultAction(
const BrowserAccessibility& node) {
- if (delegate_)
- delegate_->AccessibilityDoDefaultAction(node.GetId());
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_DO_DEFAULT;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
+void BrowserAccessibilityManager::Increment(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_INCREMENT;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
+void BrowserAccessibilityManager::ShowContextMenu(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_SHOW_CONTEXT_MENU;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::ScrollToMakeVisible(
const BrowserAccessibility& node, gfx::Rect subfocus) {
- if (delegate_) {
- delegate_->AccessibilityScrollToMakeVisible(node.GetId(), subfocus);
- }
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.target_node_id = node.GetId();
+ action_data.action = ui::AX_ACTION_SCROLL_TO_MAKE_VISIBLE;
+ action_data.target_rect = subfocus;
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::ScrollToPoint(
const BrowserAccessibility& node, gfx::Point point) {
- if (delegate_) {
- delegate_->AccessibilityScrollToPoint(node.GetId(), point);
- }
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.target_node_id = node.GetId();
+ action_data.action = ui::AX_ACTION_SCROLL_TO_POINT;
+ action_data.target_point = point;
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::SetScrollOffset(
const BrowserAccessibility& node, gfx::Point offset) {
- if (delegate_) {
- delegate_->AccessibilitySetScrollOffset(node.GetId(), offset);
- }
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.target_node_id = node.GetId();
+ action_data.action = ui::AX_ACTION_SET_SCROLL_OFFSET;
+ action_data.target_point = offset;
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::SetValue(
const BrowserAccessibility& node,
const base::string16& value) {
- if (delegate_)
- delegate_->AccessibilitySetValue(node.GetId(), value);
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.target_node_id = node.GetId();
+ action_data.action = ui::AX_ACTION_SET_VALUE;
+ action_data.value = value;
+ delegate_->AccessibilityPerformAction(action_data);
}
void BrowserAccessibilityManager::SetTextSelection(
const BrowserAccessibility& node,
int start_offset,
int end_offset) {
- if (delegate_) {
- delegate_->AccessibilitySetSelection(node.GetId(), start_offset,
- node.GetId(), end_offset);
- }
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.anchor_node_id = node.GetId();
+ action_data.anchor_offset = start_offset;
+ action_data.focus_node_id = node.GetId();
+ action_data.focus_offset = end_offset;
+ action_data.action = ui::AX_ACTION_SET_SELECTION;
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
+void BrowserAccessibilityManager::SetAccessibilityFocus(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_SET_ACCESSIBILITY_FOCUS;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
+void BrowserAccessibilityManager::HitTest(const gfx::Point& point) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ui::AX_ACTION_HIT_TEST;
+ action_data.target_point = point;
+ delegate_->AccessibilityPerformAction(action_data);
}
gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
@@ -1090,4 +1187,55 @@ BrowserAccessibilityManager::SnapshotAXTreeForTesting() {
return update;
}
+BrowserAccessibility* BrowserAccessibilityManager::CachingAsyncHitTest(
+ const gfx::Point& screen_point) {
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (root_manager && root_manager != this)
+ return root_manager->CachingAsyncHitTest(screen_point);
+
+ if (delegate()) {
+ // This triggers an asynchronous request to compute the true object that's
+ // under |screen_point|.
+ HitTest(screen_point - GetViewBounds().OffsetFromOrigin());
+
+ // Unfortunately we still have to return an answer synchronously because
+ // the APIs were designed that way. The best case scenario is that the
+ // screen point is within the bounds of the last result we got from a
+ // call to AccessibilityHitTest - in that case, we can return that object!
+ if (last_hover_bounds_.Contains(screen_point)) {
+ BrowserAccessibilityManager* manager =
+ BrowserAccessibilityManager::FromID(last_hover_ax_tree_id_);
+ if (manager) {
+ BrowserAccessibility* node = manager->GetFromID(last_hover_node_id_);
+ if (node)
+ return node;
+ }
+ }
+ }
+
+ // If that test failed we have to fall back on searching the accessibility
+ // tree locally for the best bounding box match. This is generally right
+ // for simple pages but wrong in cases of z-index, overflow, and other
+ // more complicated layouts. The hope is that if the user is moving the
+ // mouse, this fallback will only be used transiently, and the asynchronous
+ // result will be used for the next call.
+ return GetRoot()->ApproximateHitTest(screen_point);
+}
+
+void BrowserAccessibilityManager::CacheHitTestResult(
+ BrowserAccessibility* hit_test_result) {
+ // Walk up to the highest ancestor that's a leaf node; we don't want to
+ // return a node that's hidden from the tree.
+ BrowserAccessibility* parent = hit_test_result->GetParent();
+ while (parent) {
+ if (parent->PlatformChildCount() == 0)
+ hit_test_result = parent;
+ parent = parent->GetParent();
+ }
+
+ last_hover_ax_tree_id_ = hit_test_result->manager()->ax_tree_id();
+ last_hover_node_id_ = hit_test_result->GetId();
+ last_hover_bounds_ = hit_test_result->GetScreenBoundsRect();
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 91b31c75814..a9a79b1b71f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -19,6 +19,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
+#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_serializable_tree.h"
#include "ui/accessibility/ax_tree_update.h"
@@ -64,28 +65,12 @@ CONTENT_EXPORT ui::AXTreeUpdate MakeAXTreeUpdate(
class CONTENT_EXPORT BrowserAccessibilityDelegate {
public:
virtual ~BrowserAccessibilityDelegate() {}
- virtual void AccessibilitySetFocus(int acc_obj_id) = 0;
- virtual void AccessibilityDoDefaultAction(int acc_obj_id) = 0;
- virtual void AccessibilityShowContextMenu(int acc_obj_id) = 0;
- virtual void AccessibilityScrollToMakeVisible(
- int acc_obj_id, const gfx::Rect& subfocus) = 0;
- virtual void AccessibilityScrollToPoint(
- int acc_obj_id, const gfx::Point& point) = 0;
- virtual void AccessibilitySetScrollOffset(
- int acc_obj_id, const gfx::Point& offset) = 0;
- virtual void AccessibilitySetSelection(int anchor_obj_id,
- int anchor_offset,
- int focus_obj_id,
- int focus_offset) = 0;
- virtual void AccessibilitySetValue(
- int acc_obj_id, const base::string16& value) = 0;
+
+ virtual void AccessibilityPerformAction(const ui::AXActionData& data) = 0;
virtual bool AccessibilityViewHasFocus() const = 0;
virtual gfx::Rect AccessibilityGetViewBounds() const = 0;
virtual gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const = 0;
- virtual void AccessibilityHitTest(
- const gfx::Point& point) = 0;
- virtual void AccessibilitySetAccessibilityFocus(int acc_obj_id) = 0;
virtual void AccessibilityFatalError() = 0;
virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0;
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0;
@@ -187,9 +172,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
void NavigationSucceeded();
void NavigationFailed();
- // Send a message to the renderer to set focus to this node.
- void SetFocus(const BrowserAccessibility& node);
-
// Pretend that the given node has focus, for testing only. Doesn't
// communicate with the renderer and doesn't fire any events.
void SetFocusLocallyForTesting(BrowserAccessibility* node);
@@ -198,32 +180,26 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// in any BrowserAccessibilityManager.
static void SetFocusChangeCallbackForTesting(const base::Closure& callback);
- // Tell the renderer to do the default action for this node.
+ // Accessibility actions. All of these are implemented asynchronously
+ // by sending a message to the renderer to perform the respective action
+ // on the given node. See the definition of |ui::AXActionData| for more
+ // information about each of these actions.
+ void Decrement(const BrowserAccessibility& node);
void DoDefaultAction(const BrowserAccessibility& node);
-
- // Tell the renderer to scroll to make |node| visible.
- // In addition, if it's not possible to make the entire object visible,
- // scroll so that the |subfocus| rect is visible at least. The subfocus
- // rect is in local coordinates of the object itself.
+ void HitTest(const gfx::Point& point);
+ void Increment(const BrowserAccessibility& node);
void ScrollToMakeVisible(
const BrowserAccessibility& node, gfx::Rect subfocus);
-
- // Tell the renderer to scroll such that |node| is at |point|,
- // where |point| is in global coordinates of the WebContents.
void ScrollToPoint(
const BrowserAccessibility& node, gfx::Point point);
-
- // If |node| is itself a scrollable container, set its scroll
- // offset to |offset|.
+ void SetFocus(const BrowserAccessibility& node);
void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
-
- // Tell the renderer to set the value of an editable text node.
void SetValue(
const BrowserAccessibility& node, const base::string16& value);
-
- // Tell the renderer to set the text selection on a node.
void SetTextSelection(
const BrowserAccessibility& node, int start_offset, int end_offset);
+ void SetAccessibilityFocus(const BrowserAccessibility& node);
+ void ShowContextMenu(const BrowserAccessibility& node);
// Retrieve the bounds of the parent View in screen coordinates.
gfx::Rect GetViewBounds();
@@ -383,6 +359,16 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// Get a snapshot of the current tree as an AXTreeUpdate.
ui::AXTreeUpdate SnapshotAXTreeForTesting();
+ // Given a point in screen coordinates, trigger an asynchronous hit test
+ // but return the best possible match instantly.
+ //
+ //
+ BrowserAccessibility* CachingAsyncHitTest(const gfx::Point& screen_point);
+
+ // Called in response to a hover event, caches the result for the next
+ // call to CachingAsyncHitTest().
+ void CacheHitTestResult(BrowserAccessibility* hit_test_result);
+
protected:
BrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate,
@@ -453,6 +439,14 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibility* last_focused_node_;
BrowserAccessibilityManager* last_focused_manager_;
+ // These cache the AX tree ID, node ID, and global screen bounds of the
+ // last object found by an asynchronous hit test. Subsequent hit test
+ // requests that remain within this object's bounds will return the same
+ // object, but will also trigger a new asynchronous hit test request.
+ int last_hover_ax_tree_id_;
+ int last_hover_node_id_;
+ gfx::Rect last_hover_bounds_;
+
// True if the root's parent is in another accessibility tree and that
// parent's child is the root. Ensures that the parent node is notified
// once when this subtree is first connected.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index ed22b2f62f4..3f7121b56d7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -54,6 +54,13 @@ bool SectionPredicate(
}
}
+bool AllInterestingNodesPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+ return android_node->IsInterestingOnAndroid();
+}
+
void AddToPredicateMap(const char* search_key_ascii,
AccessibilityMatchPredicate predicate) {
base::string16 search_key_utf16 = base::ASCIIToUTF16(search_key_ascii);
@@ -105,14 +112,9 @@ AccessibilityMatchPredicate PredicateForSearchKey(
if (iter != g_search_key_to_predicate_map.Get().end())
return iter->second;
- // If we don't recognize the selector, return any element that's clickable.
- // We mark all focusable nodes and leaf nodes as clickable because it's
- // impossible to know whether a web node has a click handler or not, so
- // to be safe we have to allow accessibility services to click on nearly
- // anything that could possibly respond to a click.
- return [](BrowserAccessibility* start, BrowserAccessibility* node) {
- return static_cast<BrowserAccessibilityAndroid*>(node)->IsClickable();
- };
+ // If we don't recognize the selector, return any element that a
+ // screen reader should navigate to.
+ return AllInterestingNodesPredicate;
}
} // anonymous namespace
@@ -346,8 +348,7 @@ void BrowserAccessibilityManagerAndroid::HitTest(
const JavaParamRef<jobject>& obj,
jint x,
jint y) {
- if (delegate())
- delegate()->AccessibilityHitTest(gfx::Point(x, y));
+ BrowserAccessibilityManager::HitTest(gfx::Point(x, y));
}
jboolean BrowserAccessibilityManagerAndroid::IsEditableText(
@@ -361,6 +362,17 @@ jboolean BrowserAccessibilityManagerAndroid::IsEditableText(
return node->IsEditableText();
}
+jboolean BrowserAccessibilityManagerAndroid::IsFocused(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jint id) {
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
+ if (!node)
+ return false;
+
+ return node->IsFocused();
+}
+
jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionStart(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
@@ -428,7 +440,8 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
node->IsFocusable(),
node->IsFocused(),
node->IsCollapsed(),
- node->IsExpanded());
+ node->IsExpanded(),
+ node->HasNonEmptyValue());
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoClassName(
env, obj, info,
base::android::ConvertUTF8ToJavaString(env, node->GetClassName()));
@@ -680,6 +693,15 @@ jboolean BrowserAccessibilityManagerAndroid::AdjustSlider(
return false;
}
+void BrowserAccessibilityManagerAndroid::ShowContextMenu(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jint id) {
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
+ if (node)
+ node->manager()->ShowContextMenu(*node);
+}
+
void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
@@ -687,19 +709,30 @@ void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
if (obj.is_null())
return;
- BrowserAccessibilityAndroid* ancestor =
- static_cast<BrowserAccessibilityAndroid*>(node->GetParent());
- while (ancestor && ancestor != GetRoot()) {
- if (ancestor->PlatformIsLeaf() ||
- (ancestor->IsFocusable() && !ancestor->HasFocusableChild())) {
- node = ancestor;
- // Don't break - we want the highest ancestor that's focusable or a
- // leaf node.
- }
- ancestor = static_cast<BrowserAccessibilityAndroid*>(ancestor->GetParent());
+ // First walk up to the nearest platform node, in case this node isn't
+ // even exposed on the platform.
+ node = node->GetClosestPlatformObject();
+
+ // If this node is uninteresting and just a wrapper around a sole
+ // interesting descendant, prefer that descendant instead.
+ const BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+ const BrowserAccessibilityAndroid* sole_interesting_node =
+ android_node->GetSoleInterestingNodeFromSubtree();
+ if (sole_interesting_node)
+ android_node = sole_interesting_node;
+
+ // Finally, if this node is still uninteresting, try to walk up to
+ // find an interesting parent.
+ while (android_node && !android_node->IsInterestingOnAndroid()) {
+ android_node = static_cast<BrowserAccessibilityAndroid*>(
+ android_node->GetParent());
}
- Java_BrowserAccessibilityManager_handleHover(env, obj, node->unique_id());
+ if (android_node) {
+ Java_BrowserAccessibilityManager_handleHover(
+ env, obj, android_node->unique_id());
+ }
}
jint BrowserAccessibilityManagerAndroid::FindElementType(
@@ -886,10 +919,7 @@ void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
if (!node)
return;
- if (node->manager()->delegate()) {
- node->manager()->delegate()->AccessibilitySetAccessibilityFocus(
- node->GetId());
- }
+ node->manager()->SetAccessibilityFocus(*node);
}
bool BrowserAccessibilityManagerAndroid::IsSlider(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index d17a6754821..e5110dc823a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -108,6 +108,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
jboolean IsEditableText(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint id);
+ jboolean IsFocused(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint id);
jint GetEditableTextSelectionStart(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -154,6 +157,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
const base::android::JavaParamRef<jobject>& obj,
jint id,
jboolean increment);
+ void ShowContextMenu(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint id);
// Return the id of the next node in tree order in the direction given by
// |forwards|, starting with |start_id|, that matches |element_type|,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index 36c983e3760..1f69769cc0b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -8,8 +8,6 @@
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
-struct ViewHostMsg_AccessibilityNotification_Params;
-
namespace content {
class BrowserAccessibilityAuraLinux;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 6b04dd40c00..e21ca6ad5f7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -67,29 +67,13 @@ class TestBrowserAccessibilityDelegate
TestBrowserAccessibilityDelegate()
: got_fatal_error_(false) {}
- void AccessibilitySetFocus(int acc_obj_id) override {}
- void AccessibilityDoDefaultAction(int acc_obj_id) override {}
- void AccessibilityShowContextMenu(int acc_obj_id) override {}
- void AccessibilityScrollToMakeVisible(int acc_obj_id,
- const gfx::Rect& subfocus) override {}
- void AccessibilityScrollToPoint(int acc_obj_id,
- const gfx::Point& point) override {}
- void AccessibilitySetScrollOffset(int acc_obj_id,
- const gfx::Point& offset) override {}
- void AccessibilitySetSelection(int acc_anchor_obj_id,
- int start_offset,
- int acc_focus_obj_id,
- int end_offset) override {}
- void AccessibilitySetValue(int acc_obj_id, const base::string16& value)
- override {}
+ void AccessibilityPerformAction(const ui::AXActionData& data) override {}
bool AccessibilityViewHasFocus() const override { return false; }
gfx::Rect AccessibilityGetViewBounds() const override { return gfx::Rect(); }
gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const override {
return gfx::Point();
}
- void AccessibilityHitTest(const gfx::Point& point) override {}
- void AccessibilitySetAccessibilityFocus(int acc_obj_id) override {}
void AccessibilityFatalError() override { got_fatal_error_ = true; }
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override {
return gfx::kNullAcceleratedWidget;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 1fe2d2cc260..cdedf7a576c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -118,7 +118,7 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
if (event_type == ui::AX_EVENT_LOAD_COMPLETE && can_fire_events)
load_complete_pending_ = false;
- if (load_complete_pending_ && can_fire_events) {
+ if (load_complete_pending_ && can_fire_events && GetRoot()) {
load_complete_pending_ = false;
NotifyAccessibilityEvent(BrowserAccessibilityEvent::FromPendingLoadComplete,
ui::AX_EVENT_LOAD_COMPLETE,
@@ -128,6 +128,7 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
if (!can_fire_events &&
!load_complete_pending_ &&
event_type == ui::AX_EVENT_LOAD_COMPLETE &&
+ GetRoot() &&
!GetRoot()->HasState(ui::AX_STATE_OFFSCREEN) &&
GetRoot()->PlatformChildCount() > 0) {
load_complete_pending_ = true;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index aca1a584140..d77d60d807d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -445,7 +445,7 @@ STDMETHODIMP BrowserAccessibilityWin::accHitTest(LONG x_left,
return S_FALSE;
}
- BrowserAccessibility* result = BrowserAccessibilityForPoint(point);
+ BrowserAccessibility* result = manager()->CachingAsyncHitTest(point);
if (result == this) {
// Point is within this object.
child->vt = VT_I4;
@@ -5438,10 +5438,13 @@ void BrowserAccessibilityWin::InitRoleAndState() {
case ui::AX_ROLE_TEXT_FIELD:
case ui::AX_ROLE_SEARCH_BOX:
ia_role = ROLE_SYSTEM_TEXT;
- if (HasState(ui::AX_STATE_MULTILINE))
+ if (HasState(ui::AX_STATE_MULTILINE)) {
ia2_state |= IA2_STATE_MULTI_LINE;
- else
+ } else {
ia2_state |= IA2_STATE_SINGLE_LINE;
+ }
+ if (HasState(ui::AX_STATE_READ_ONLY))
+ ia_state |= STATE_SYSTEM_READONLY;
ia2_state |= IA2_STATE_SELECTABLE_TEXT;
break;
case ui::AX_ROLE_ABBR:
@@ -5496,11 +5499,11 @@ void BrowserAccessibilityWin::InitRoleAndState() {
// Compute the final value of READONLY for MSAA.
//
// We always set the READONLY state for elements that have the
- // aria-readonly attribute and for a few roles (in the switch above).
- // We clear the READONLY state on focusable controls and on a document.
- // Everything else, the majority of objects, do not have this state set.
- if (HasState(ui::AX_STATE_FOCUSABLE) &&
- ia_role != ROLE_SYSTEM_DOCUMENT) {
+ // aria-readonly attribute and for a few roles (in the switch above),
+ // including read-only text fields.
+ // The majority of focusable controls should not have the read-only state set.
+ if (HasState(ui::AX_STATE_FOCUSABLE) && ia_role != ROLE_SYSTEM_DOCUMENT &&
+ ia_role != ROLE_SYSTEM_TEXT) {
ia_state &= ~(STATE_SYSTEM_READONLY);
}
if (!HasState(ui::AX_STATE_READ_ONLY))
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index a37b7808d86..ee246198d92 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -239,7 +239,6 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
text2.id = 2;
text2.role = ui::AX_ROLE_STATIC_TEXT;
text2.SetName("new text");
- text2.SetName("old text");
AXEventNotificationDetails param;
param.event_type = ui::AX_EVENT_CHILDREN_CHANGED;
param.update.nodes.push_back(text2);
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index fd13b952a4e..b694772a865 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -87,8 +87,8 @@ void DumpAccessibilityTestBase::SetUpCommandLine(
void DumpAccessibilityTestBase::SetUpOnMainThread() {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
base::string16
@@ -197,12 +197,6 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- // Output the test path to help anyone who encounters a failure and needs
- // to know where to look.
- LOG(INFO) << "Testing: " << file_path.LossyDisplayName()
- << (is_blink_pass_ ? " (internal Blink accessibility tree)"
- : " (native accessibility tree for this platform)");
-
std::string html_contents;
base::FilePath expected_file;
std::string expected_contents_raw;
@@ -229,6 +223,13 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
base::ReadFileToString(expected_file, &expected_contents_raw);
}
+ // Output the test path to help anyone who encounters a failure and needs
+ // to know where to look.
+ LOG(INFO) << "Testing: "
+ << file_path.NormalizePathSeparatorsTo('/').LossyDisplayName();
+ LOG(INFO) << "Expected output: "
+ << expected_file.NormalizePathSeparatorsTo('/').LossyDisplayName();
+
// Tolerate Windows-style line endings (\r\n) in the expected file:
// normalize by deleting all \r from the file (if any) to leave only \n.
std::string expected_contents;
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index b81c4ac4cce..28daec1a006 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -93,7 +93,6 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
waiter.reset(new AccessibilityNotificationWaiter(
shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
-
web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("go()"));
@@ -109,7 +108,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_HOVER));
BrowserAccessibilityManager* manager =
web_contents->GetRootBrowserAccessibilityManager();
- manager->delegate()->AccessibilityHitTest(gfx::Point(0, 0));
+ manager->HitTest(gfx::Point(0, 0));
waiter->WaitForNotification();
// Save a copy of the final accessibility tree (as a text dump); we'll
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index af2f214c126..f88e9788ed9 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1080,6 +1080,12 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("input-text.html"));
}
+// Fails on Android GN bot, see crbug.com/569542.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ MAYBE(AccessibilityInputTextReadOnly)) {
+ RunHtmlTest(FILE_PATH_LITERAL("input-text-read-only.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityInputTextNameCalc) {
RunHtmlTest(FILE_PATH_LITERAL("input-text-name-calc.html"));
@@ -1349,7 +1355,12 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTextarea) {
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityTextareaWithSelection) {
+ AccessibilityTextareaReadOnly) {
+ RunHtmlTest(FILE_PATH_LITERAL("textarea-read-only.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityTextareaWithSelection) {
RunHtmlTest(FILE_PATH_LITERAL("textarea-with-selection.html"));
}
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
index f1e6d9e3179..fb9c6707c09 100644
--- a/chromium/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -2,28 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.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/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
@@ -48,7 +34,7 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
for (FrameTreeNode* node : frame_tree->Nodes())
hover_waiter.ListenToAdditionalFrame(node->current_frame_host());
- manager->delegate()->AccessibilityHitTest(point);
+ manager->HitTest(point);
hover_waiter.WaitForNotification();
RenderFrameHostImpl* target_frame = hover_waiter.event_render_frame_host();
@@ -59,6 +45,26 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
target_manager->GetFromID(hover_target_id);
return hovered_node;
}
+
+ BrowserAccessibility* CallCachingAsyncHitTest(const gfx::Point& point) {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTree* frame_tree = web_contents->GetFrameTree();
+ BrowserAccessibilityManager* manager =
+ web_contents->GetRootBrowserAccessibilityManager();
+ gfx::Point screen_point =
+ point + manager->GetViewBounds().OffsetFromOrigin();
+
+ // Each call to CachingAsyncHitTest results in at least one HOVER
+ // event received. Block until we receive it.
+ AccessibilityNotificationWaiter hover_waiter(
+ shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ hover_waiter.ListenToAdditionalFrame(node->current_frame_host());
+ BrowserAccessibility* result = manager->CachingAsyncHitTest(screen_point);
+ hover_waiter.WaitForNotification();
+ return result;
+ }
};
IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
@@ -144,4 +150,72 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole());
}
+IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
+ CachingAsyncHitTestingInIframes) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ GURL url(embedded_test_server()->GetURL(
+ "/accessibility/hit_testing/hit_testing.html"));
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Ordinary Button");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Scrolled Button");
+
+ // For each point we try, the first time we call CachingAsyncHitTest it
+ // should FAIL and return the wrong object, because this test page has
+ // been designed to confound local synchronous hit testing using
+ // z-indexes. However, calling CachingAsyncHitTest a second time should
+ // return the correct result (since CallCachingAsyncHitTest waits for the
+ // HOVER event to be received).
+
+ // (50, 50) -> "Button"
+ BrowserAccessibility* hovered_node;
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 50));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_NE(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 50));
+ ASSERT_EQ("Button", hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 305) -> div in first iframe
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 305));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_NE(ui::AX_ROLE_DIV, hovered_node->GetRole());
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 305));
+ ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole());
+
+ // (50, 350) -> "Ordinary Button"
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 350));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_NE(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 350));
+ ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ ASSERT_EQ("Ordinary Button",
+ hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 455) -> "Scrolled Button"
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 455));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_NE(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 455));
+ ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ ASSERT_EQ("Scrolled Button",
+ hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 505) -> div in second iframe
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 505));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_NE(ui::AX_ROLE_DIV, hovered_node->GetRole());
+ hovered_node = CallCachingAsyncHitTest(gfx::Point(50, 505));
+ ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole());
+}
+
} // namespace content
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 4923e25ef9b..bd54a8da87a 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -153,7 +153,7 @@ void OneShotAccessibilityTreeSearch::SearchByIteratingOverChildren() {
void OneShotAccessibilityTreeSearch::SearchByWalkingTree() {
BrowserAccessibility* node = nullptr;
node = start_node_;
- if (node != scope_node_) {
+ if (node != scope_node_ || result_limit_ == 1) {
if (direction_ == FORWARDS)
node = tree_->NextInTreeOrder(start_node_);
else
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 21dc1c5f687..9b34ad36ce8 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
@@ -96,6 +96,15 @@ TEST_F(MAYBE_OneShotAccessibilityTreeSearchTest, GetAll) {
ASSERT_EQ(6U, search.CountMatches());
}
+TEST_F(MAYBE_OneShotAccessibilityTreeSearchTest, NoCycle) {
+ // If you set a result limit of 1, you won't get the root node back as
+ // the first match.
+ OneShotAccessibilityTreeSearch search(tree_->GetRoot());
+ search.SetResultLimit(1);
+ ASSERT_EQ(1U, search.CountMatches());
+ EXPECT_NE(1, search.GetMatchAtIndex(0)->GetId());
+}
+
TEST_F(MAYBE_OneShotAccessibilityTreeSearchTest, ForwardsWithStartNode) {
OneShotAccessibilityTreeSearch search(tree_->GetRoot());
search.SetStartNode(tree_->GetFromID(4));
diff --git a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
index 60a4639c360..c7e1e8c9d6f 100644
--- a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
+++ b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -29,8 +29,8 @@ class TouchAccessibilityBrowserTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
void NavigateToUrlAndWaitForAccessibilityTree(const GURL& url) {
diff --git a/chromium/content/browser/android/app_web_message_port_message_filter.cc b/chromium/content/browser/android/app_web_message_port_message_filter.cc
new file mode 100644
index 00000000000..b95ea00ffd5
--- /dev/null
+++ b/chromium/content/browser/android/app_web_message_port_message_filter.cc
@@ -0,0 +1,97 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/app_web_message_port_message_filter.h"
+
+#include "content/browser/android/app_web_message_port_service_impl.h"
+#include "content/browser/message_port_service.h"
+#include "content/common/app_web_message_port_messages.h"
+#include "content/public/browser/android/app_web_message_port_service.h"
+#include "content/public/browser/message_port_provider.h"
+
+using content::BrowserThread;
+using content::MessagePortProvider;
+
+namespace content {
+
+AppWebMessagePortMessageFilter::AppWebMessagePortMessageFilter(int route_id)
+ : BrowserMessageFilter(AwMessagePortMsgStart), route_id_(route_id) {}
+
+AppWebMessagePortMessageFilter::~AppWebMessagePortMessageFilter() {}
+
+void AppWebMessagePortMessageFilter::OnChannelClosing() {
+ MessagePortService::GetInstance()->OnMessagePortDelegateClosing(this);
+ AppWebMessagePortServiceImpl::GetInstance()
+ ->OnMessagePortMessageFilterClosing(this);
+}
+
+bool AppWebMessagePortMessageFilter::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(AppWebMessagePortMessageFilter, message)
+ IPC_MESSAGE_FORWARD(
+ AppWebMessagePortHostMsg_ConvertedWebToAppMessage,
+ AppWebMessagePortServiceImpl::GetInstance(),
+ AppWebMessagePortServiceImpl::OnConvertedWebToAppMessage)
+ IPC_MESSAGE_HANDLER(AppWebMessagePortHostMsg_ConvertedAppToWebMessage,
+ OnConvertedAppToWebMessage)
+ IPC_MESSAGE_HANDLER(AppWebMessagePortHostMsg_ClosePortAck, OnClosePortAck)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void AppWebMessagePortMessageFilter::OnConvertedAppToWebMessage(
+ int msg_port_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids) {
+ MessagePortService* msp = MessagePortService::GetInstance();
+ msp->PostMessage(msg_port_id, message, sent_message_port_ids);
+}
+
+void AppWebMessagePortMessageFilter::OnClosePortAck(int message_port_id) {
+ MessagePortService* msp = MessagePortService::GetInstance();
+ msp->ClosePort(message_port_id);
+ AppWebMessagePortServiceImpl::GetInstance()->CleanupPort(message_port_id);
+}
+
+void AppWebMessagePortMessageFilter::OnDestruct() const {
+ BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+void AppWebMessagePortMessageFilter::SendAppToWebMessage(
+ int msg_port_route_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids) {
+ Send(new AppWebMessagePortMsg_AppToWebMessage(
+ route_id_,
+ msg_port_route_id, // same as the port id
+ message, sent_message_port_ids));
+}
+
+void AppWebMessagePortMessageFilter::SendClosePortMessage(int message_port_id) {
+ Send(new AppWebMessagePortMsg_ClosePort(route_id_, message_port_id));
+}
+
+void AppWebMessagePortMessageFilter::SendMessage(
+ int msg_port_route_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids) {
+ MessagePortService* msp = MessagePortService::GetInstance();
+ for (int sent_port_id : sent_message_port_ids) {
+ msp->HoldMessages(sent_port_id);
+ msp->UpdateMessagePort(sent_port_id, this, sent_port_id);
+ }
+ Send(new AppWebMessagePortMsg_WebToAppMessage(
+ route_id_,
+ msg_port_route_id, // same as the port id
+ message, sent_message_port_ids));
+}
+
+void AppWebMessagePortMessageFilter::SendMessagesAreQueued(int route_id) {
+ // TODO(sgurun) implement
+ NOTREACHED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/app_web_message_port_message_filter.h b/chromium/content/browser/android/app_web_message_port_message_filter.h
new file mode 100644
index 00000000000..b9658eb7e23
--- /dev/null
+++ b/chromium/content/browser/android/app_web_message_port_message_filter.h
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_MESSAGE_FILTER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/message_port_delegate.h"
+
+namespace content {
+
+// Filter for Aw specific MessagePort related IPC messages (creating and
+// destroying a MessagePort, sending a message via a MessagePort etc).
+class AppWebMessagePortMessageFilter : public content::BrowserMessageFilter,
+ public content::MessagePortDelegate {
+ public:
+ explicit AppWebMessagePortMessageFilter(int route_id);
+
+ // BrowserMessageFilter implementation.
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() const override;
+
+ void SendAppToWebMessage(int msg_port_route_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids);
+ void SendClosePortMessage(int message_port_id);
+
+ // MessagePortDelegate implementation.
+ void SendMessage(int msg_port_route_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_ports) override;
+ void SendMessagesAreQueued(int route_id) override;
+
+ private:
+ friend class content::BrowserThread;
+ friend class base::DeleteHelper<AppWebMessagePortMessageFilter>;
+
+ void OnConvertedAppToWebMessage(
+ int msg_port_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids);
+ void OnClosePortAck(int message_port_id);
+
+ int route_id_;
+
+ ~AppWebMessagePortMessageFilter() override;
+
+ DISALLOW_COPY_AND_ASSIGN(AppWebMessagePortMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/android/app_web_message_port_service_impl.cc b/chromium/content/browser/android/app_web_message_port_service_impl.cc
new file mode 100644
index 00000000000..2dd13b907b6
--- /dev/null
+++ b/chromium/content/browser/android/app_web_message_port_service_impl.cc
@@ -0,0 +1,251 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/app_web_message_port_service_impl.h"
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/bind.h"
+#include "content/browser/android/app_web_message_port_message_filter.h"
+#include "content/browser/message_port_service.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/message_port_provider.h"
+#include "jni/AppWebMessagePortService_jni.h"
+
+namespace content {
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF16;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::ToJavaIntArray;
+using content::BrowserThread;
+using content::MessagePortProvider;
+
+AppWebMessagePortServiceImpl* AppWebMessagePortServiceImpl::GetInstance() {
+ return base::Singleton<AppWebMessagePortServiceImpl>::get();
+}
+
+AppWebMessagePortServiceImpl::AppWebMessagePortServiceImpl() {}
+
+AppWebMessagePortServiceImpl::~AppWebMessagePortServiceImpl() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+ Java_AppWebMessagePortService_unregisterNativeAppWebMessagePortService(env,
+ obj);
+}
+
+void AppWebMessagePortServiceImpl::Init(JNIEnv* env, jobject obj) {
+ java_ref_ = JavaObjectWeakGlobalRef(env, obj);
+}
+
+void AppWebMessagePortServiceImpl::CreateMessageChannel(
+ JNIEnv* env,
+ jobjectArray ports,
+ WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
+ int routing_id = web_contents->GetMainFrame()->GetRoutingID();
+ scoped_refptr<AppWebMessagePortMessageFilter> filter =
+ rfh->GetAppWebMessagePortMessageFilter(routing_id);
+ ScopedJavaGlobalRef<jobjectArray>* j_ports =
+ new ScopedJavaGlobalRef<jobjectArray>();
+ j_ports->Reset(env, ports);
+
+ int* portId1 = new int;
+ int* portId2 = new int;
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AppWebMessagePortServiceImpl::CreateMessageChannelOnIOThread,
+ base::Unretained(this), filter, portId1, portId2),
+ base::Bind(&AppWebMessagePortServiceImpl::OnMessageChannelCreated,
+ base::Unretained(this), base::Owned(j_ports),
+ base::Owned(portId1), base::Owned(portId2)));
+}
+
+void AppWebMessagePortServiceImpl::OnConvertedWebToAppMessage(
+ int message_port_id,
+ const base::ListValue& message,
+ const std::vector<int>& sent_message_port_ids) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> jobj = java_ref_.get(env);
+ if (jobj.is_null())
+ return;
+
+ base::string16 value;
+ if (!message.GetString(0, &value)) {
+ LOG(WARNING) << "Converting post message to a string failed for port "
+ << message_port_id;
+ return;
+ }
+
+ if (message.GetSize() != 1) {
+ NOTREACHED();
+ return;
+ }
+
+ // Add the ports to AppWebMessagePortService.
+ for (const auto& iter : sent_message_port_ids) {
+ AddPort(iter, ports_[message_port_id]);
+ }
+
+ ScopedJavaLocalRef<jstring> jmsg = ConvertUTF16ToJavaString(env, value);
+ ScopedJavaLocalRef<jintArray> jports =
+ ToJavaIntArray(env, sent_message_port_ids);
+ Java_AppWebMessagePortService_onReceivedMessage(env, jobj, message_port_id,
+ jmsg, jports);
+}
+
+void AppWebMessagePortServiceImpl::OnMessagePortMessageFilterClosing(
+ AppWebMessagePortMessageFilter* filter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (MessagePorts::iterator iter = ports_.begin(); iter != ports_.end();
+ iter++) {
+ if (iter->second == filter) {
+ ports_.erase(iter);
+ }
+ }
+}
+
+void AppWebMessagePortServiceImpl::PostAppToWebMessage(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ int sender_id,
+ const JavaParamRef<jstring>& message,
+ const JavaParamRef<jintArray>& sent_ports) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::string16* j_message = new base::string16;
+ ConvertJavaStringToUTF16(env, message, j_message);
+ std::vector<int>* j_sent_ports = new std::vector<int>;
+ if (sent_ports != nullptr)
+ base::android::JavaIntArrayToIntVector(env, sent_ports, j_sent_ports);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AppWebMessagePortServiceImpl::PostAppToWebMessageOnIOThread,
+ base::Unretained(this), sender_id, base::Owned(j_message),
+ base::Owned(j_sent_ports)));
+}
+
+// The message port service cannot immediately close the port, because
+// it is possible that messages are still queued in the renderer process
+// waiting for a conversion. Instead, it sends a special message with
+// a flag which indicates that this message port should be closed.
+void AppWebMessagePortServiceImpl::ClosePort(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ int message_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AppWebMessagePortServiceImpl::PostClosePortMessage,
+ base::Unretained(this), message_port_id));
+}
+
+void AppWebMessagePortServiceImpl::ReleaseMessages(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ int message_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&MessagePortService::ReleaseMessages,
+ base::Unretained(MessagePortService::GetInstance()),
+ message_port_id));
+}
+
+void AppWebMessagePortServiceImpl::RemoveSentPorts(
+ const std::vector<int>& sent_ports) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Remove the filters that are associated with the transferred ports
+ for (const auto& iter : sent_ports)
+ ports_.erase(iter);
+}
+
+void AppWebMessagePortServiceImpl::PostAppToWebMessageOnIOThread(
+ int sender_id,
+ base::string16* message,
+ std::vector<int>* sent_ports) {
+ RemoveSentPorts(*sent_ports);
+ ports_[sender_id]->SendAppToWebMessage(sender_id, *message, *sent_ports);
+}
+
+void AppWebMessagePortServiceImpl::PostClosePortMessage(int message_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ports_[message_port_id]->SendClosePortMessage(message_port_id);
+}
+
+void AppWebMessagePortServiceImpl::CleanupPort(int message_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ports_.erase(message_port_id);
+}
+
+void AppWebMessagePortServiceImpl::CreateMessageChannelOnIOThread(
+ scoped_refptr<AppWebMessagePortMessageFilter> filter,
+ int* portId1,
+ int* portId2) {
+ *portId1 = 0;
+ *portId2 = 0;
+ MessagePortService* msp = MessagePortService::GetInstance();
+ msp->Create(MSG_ROUTING_NONE, filter.get(), portId1);
+ msp->Create(MSG_ROUTING_NONE, filter.get(), portId2);
+ // Update the routing number of the message ports to be equal to the message
+ // port numbers.
+ msp->UpdateMessagePort(*portId1, filter.get(), *portId1);
+ msp->UpdateMessagePort(*portId2, filter.get(), *portId2);
+ msp->Entangle(*portId1, *portId2);
+ msp->Entangle(*portId2, *portId1);
+
+ msp->HoldMessages(*portId1);
+ msp->HoldMessages(*portId2);
+ AddPort(*portId1, filter.get());
+ AddPort(*portId2, filter.get());
+}
+
+void AppWebMessagePortServiceImpl::OnMessageChannelCreated(
+ ScopedJavaGlobalRef<jobjectArray>* ports,
+ int* port1,
+ int* port2) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+ Java_AppWebMessagePortService_onMessageChannelCreated(env, obj, *port1,
+ *port2, *ports);
+}
+
+// Adds a new port to the message port service.
+void AppWebMessagePortServiceImpl::AddPort(
+ int message_port_id,
+ AppWebMessagePortMessageFilter* filter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (ports_.count(message_port_id)) {
+ NOTREACHED();
+ return;
+ }
+ ports_[message_port_id] = filter;
+}
+
+bool RegisterAppWebMessagePortService(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// static
+jlong InitAppWebMessagePortService(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ AppWebMessagePortServiceImpl* service =
+ AppWebMessagePortServiceImpl::GetInstance();
+ service->Init(env, obj);
+ return reinterpret_cast<intptr_t>(service);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/app_web_message_port_service_impl.h b/chromium/content/browser/android/app_web_message_port_service_impl.h
new file mode 100644
index 00000000000..e43785ba423
--- /dev/null
+++ b/chromium/content/browser/android/app_web_message_port_service_impl.h
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_SERVICE_IMPL_H_
+
+#include <map>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/strings/string16.h"
+#include "content/public/browser/android/app_web_message_port_service.h"
+
+namespace content {
+class AppWebMessagePortMessageFilter;
+
+// This class is the native peer of AppWebMessagePortService.java.
+// Please see the java class for an explanation of use, ownership and lifetime.
+
+// Threading: Created and initialized on UI thread. For other methods, see
+// the method level DCHECKS or documentation.
+class AppWebMessagePortServiceImpl : public AppWebMessagePortService {
+ public:
+ // Returns the AppWebMessagePortServiceImpl singleton.
+ static AppWebMessagePortServiceImpl* GetInstance();
+
+ AppWebMessagePortServiceImpl();
+ ~AppWebMessagePortServiceImpl() override;
+ void Init(JNIEnv* env, jobject object);
+
+ // AppWebMessagePortService implementation
+
+ void CreateMessageChannel(JNIEnv* env,
+ jobjectArray ports,
+ WebContents* web_contents) override;
+ void CleanupPort(int message_port_id) override;
+
+ // Methods called from Java.
+ void PostAppToWebMessage(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& object,
+ int sender_id,
+ const base::android::JavaParamRef<jstring>& message,
+ const base::android::JavaParamRef<jintArray>& sent_ports);
+ void ClosePort(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& object,
+ int message_port_id);
+ void ReleaseMessages(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& object,
+ int message_port_id);
+
+ void OnMessagePortMessageFilterClosing(
+ AppWebMessagePortMessageFilter* filter);
+
+ // AppWebMessagePortServiceImpl specific calls
+ void OnConvertedWebToAppMessage(
+ int message_port_id,
+ const base::ListValue& message,
+ const std::vector<int>& sent_message_port_ids);
+ void RemoveSentPorts(const std::vector<int>& sent_ports);
+
+ private:
+ friend struct base::DefaultSingletonTraits<AppWebMessagePortServiceImpl>;
+
+ void PostAppToWebMessageOnIOThread(int sender_id,
+ base::string16* message,
+ std::vector<int>* sent_ports);
+ void CreateMessageChannelOnIOThread(
+ scoped_refptr<AppWebMessagePortMessageFilter> filter,
+ int* port1,
+ int* port2);
+ void OnMessageChannelCreated(
+ base::android::ScopedJavaGlobalRef<jobjectArray>* ports,
+ int* port1,
+ int* port2);
+ void AddPort(int message_port_id, AppWebMessagePortMessageFilter* filter);
+ void PostClosePortMessage(int message_port_id);
+
+ JavaObjectWeakGlobalRef java_ref_;
+ typedef std::map<int, AppWebMessagePortMessageFilter*> MessagePorts;
+ MessagePorts ports_; // Access on IO thread
+
+ DISALLOW_COPY_AND_ASSIGN(AppWebMessagePortServiceImpl);
+};
+
+bool RegisterAppWebMessagePortService(JNIEnv* env);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index d2733833f9a..94a377c21a4 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -22,6 +22,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
+#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h"
#include "ui/gl/android/surface_texture.h"
@@ -213,25 +214,6 @@ void CompleteScopedSurfaceRequest(JNIEnv* env,
gl::ScopedJavaSurface(jsurface));
}
-void RegisterViewSurface(int surface_id, const JavaRef<jobject>& j_surface) {
- JNIEnv* env = AttachCurrentThread();
- DCHECK(env);
- Java_ChildProcessLauncher_registerViewSurface(env, surface_id, j_surface);
-}
-
-void UnregisterViewSurface(int surface_id) {
- JNIEnv* env = AttachCurrentThread();
- DCHECK(env);
- Java_ChildProcessLauncher_unregisterViewSurface(env, surface_id);
-}
-
-gl::ScopedJavaSurface GetViewSurface(int surface_id) {
- JNIEnv* env = AttachCurrentThread();
- DCHECK(env);
- return gl::ScopedJavaSurface::AcquireExternalSurface(
- Java_ChildProcessLauncher_getViewSurface(env, surface_id).obj());
-}
-
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
gl::SurfaceTexture* surface_texture) {
@@ -263,6 +245,14 @@ jboolean IsSingleProcess(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
switches::kSingleProcess);
}
+base::android::ScopedJavaLocalRef<jobject> GetViewSurface(JNIEnv* env,
+ const base::android::JavaParamRef<jclass>& jcaller,
+ jint surface_id) {
+ gl::ScopedJavaSurface surface_view =
+ gpu::GpuSurfaceTracker::GetInstance()->AcquireJavaSurface(surface_id);
+ return base::android::ScopedJavaLocalRef<jobject>(surface_view.j_surface());
+}
+
bool RegisterChildProcessLauncher(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chromium/content/browser/android/child_process_launcher_android.h b/chromium/content/browser/android/child_process_launcher_android.h
index f97e5a9fa1e..0dbebc2680a 100644
--- a/chromium/content/browser/android/child_process_launcher_android.h
+++ b/chromium/content/browser/android/child_process_launcher_android.h
@@ -41,13 +41,6 @@ bool IsChildProcessOomProtected(base::ProcessHandle handle);
void SetChildProcessInForeground(base::ProcessHandle handle,
bool in_foreground);
-void RegisterViewSurface(int surface_id,
- const base::android::JavaRef<jobject>& j_surface);
-
-void UnregisterViewSurface(int surface_id);
-
-gl::ScopedJavaSurface GetViewSurface(int surface_id);
-
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
gl::SurfaceTexture* surface_texture);
diff --git a/chromium/content/browser/android/composited_touch_handle_drawable.cc b/chromium/content/browser/android/composited_touch_handle_drawable.cc
index a3a9d9c04e7..859c4702f3d 100644
--- a/chromium/content/browser/android/composited_touch_handle_drawable.cc
+++ b/chromium/content/browser/android/composited_touch_handle_drawable.cc
@@ -24,7 +24,7 @@ static SkBitmap CreateSkBitmapFromJavaBitmap(
base::android::ScopedJavaLocalRef<jobject> jbitmap) {
return jbitmap.is_null()
? SkBitmap()
- : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap.obj()));
+ : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap));
}
class HandleResources {
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index 2d9e4704401..4854e8be748 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -52,7 +53,7 @@
#include "device/geolocation/geolocation_service_context.h"
#include "jni/ContentViewCore_jni.h"
#include "jni/DragEvent_jni.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
#include "ui/base/clipboard/clipboard.h"
@@ -61,6 +62,7 @@
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event_utils.h"
+#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -76,6 +78,7 @@ using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
using blink::WebGestureEvent;
using blink::WebInputEvent;
+using ui::MotionEventAndroid;
namespace content {
@@ -160,6 +163,17 @@ int ToGestureEventType(WebInputEvent::Type type) {
}
}
+void RecordToolTypeForActionDown(MotionEventAndroid& event) {
+ MotionEventAndroid::Action action = event.GetAction();
+ if (action == MotionEventAndroid::ACTION_DOWN ||
+ action == MotionEventAndroid::ACTION_POINTER_DOWN ||
+ action == MotionEventAndroid::ACTION_BUTTON_PRESS) {
+ UMA_HISTOGRAM_ENUMERATION("Event.AndroidActionDown.ToolType",
+ event.GetToolType(0),
+ MotionEventAndroid::TOOL_TYPE_LAST + 1);
+ }
+}
+
} // namespace
// Enables a callback when the underlying WebContents is destroyed, to enable
@@ -207,27 +221,20 @@ ContentViewCoreImpl::ContentViewCoreImpl(
JNIEnv* env,
const JavaRef<jobject>& obj,
WebContents* web_contents,
- const JavaRef<jobject>& view_android_delegate,
- ui::WindowAndroid* window_android,
+ float dpi_scale,
const JavaRef<jobject>& java_bridge_retained_object_set)
: WebContentsObserver(web_contents),
java_ref_(env, obj),
- view_(view_android_delegate),
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
page_scale_(1),
- dpi_scale_(ui::GetScaleFactorForNativeView(&view_)),
+ dpi_scale_(dpi_scale),
device_orientation_(0),
accessibility_enabled_(false) {
- CHECK(web_contents) <<
- "A ContentViewCoreImpl should be created with a valid WebContents.";
- DCHECK(window_android);
- DCHECK(!view_android_delegate.is_null());
- window_android->AddChild(&view_);
- view_.SetLayer(cc::Layer::Create());
+ GetViewAndroid()->SetLayer(cc::Layer::Create());
gfx::Size physical_size(
Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
- view_.GetLayer()->SetBounds(physical_size);
+ GetViewAndroid()->GetLayer()->SetBounds(physical_size);
// Currently, the only use case we have for overriding a user agent involves
// spoofing a desktop Linux user agent for "Request desktop site".
@@ -257,10 +264,8 @@ void ContentViewCoreImpl::RemoveObserver(
}
ContentViewCoreImpl::~ContentViewCoreImpl() {
- view_.GetLayer()->RemoveFromParent();
- FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
- observer_list_,
- OnContentViewCoreDestroyed());
+ for (auto& observer : observer_list_)
+ observer.OnContentViewCoreDestroyed();
observer_list_.Clear();
JNIEnv* env = base::android::AttachCurrentThread();
@@ -276,19 +281,20 @@ void ContentViewCoreImpl::UpdateWindowAndroid(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong window_android) {
- if (window_android) {
- DCHECK(!view_.GetWindowAndroid());
- ui::WindowAndroid* window =
- reinterpret_cast<ui::WindowAndroid*>(window_android);
- window->AddChild(&view_);
- FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
- observer_list_,
- OnAttachedToWindow());
- } else {
- FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
- observer_list_,
- OnDetachedFromWindow());
- view_.RemoveFromParent();
+ ui::ViewAndroid* view = GetViewAndroid();
+ ui::WindowAndroid* window =
+ reinterpret_cast<ui::WindowAndroid*>(window_android);
+ if (window == GetWindowAndroid())
+ return;
+ if (GetWindowAndroid()) {
+ for (auto& observer : observer_list_)
+ observer.OnDetachedFromWindow();
+ view->RemoveFromParent();
+ }
+ if (window) {
+ window->AddChild(view);
+ for (auto& observer : observer_list_)
+ observer.OnAttachedToWindow();
}
}
@@ -301,9 +307,9 @@ ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env,
base::android::ScopedJavaLocalRef<jobject>
ContentViewCoreImpl::GetJavaWindowAndroid(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
- if (!view_.GetWindowAndroid())
+ if (!GetWindowAndroid())
return ScopedJavaLocalRef<jobject>();
- return view_.GetWindowAndroid()->GetJavaObject();
+ return GetWindowAndroid()->GetJavaObject();
}
void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(
@@ -402,13 +408,6 @@ jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
return rwhva->GetCachedBackgroundColor();
}
-void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
- if (should_pause)
- web_contents_->GetGeolocationServiceContext()->PauseUpdates();
- else
- web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
-}
-
// All positions and sizes are in CSS pixels.
// Note that viewport_width/height is a best effort based.
// ContentViewCore has the actual information about the physical viewport size.
@@ -426,10 +425,10 @@ void ContentViewCoreImpl::UpdateFrameInfo(
const gfx::SelectionBound& selection_start) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null() || !view_.GetWindowAndroid())
+ if (obj.is_null() || !GetWindowAndroid())
return;
- view_.GetWindowAndroid()->set_content_offset(
+ GetWindowAndroid()->set_content_offset(
gfx::Vector2dF(0.0f, top_controls_height * top_controls_shown_ratio));
page_scale_ = page_scale_factor;
@@ -523,11 +522,12 @@ void ContentViewCoreImpl::ShowSelectPopupMenu(
}
ScopedJavaLocalRef<jobjectArray> items_array(
base::android::ToJavaArrayOfStrings(env, labels));
- select_popup_ = view_.AcquireAnchorView();
+ ui::ViewAndroid* view = GetViewAndroid();
+ select_popup_ = view->AcquireAnchorView();
const ScopedJavaLocalRef<jobject> popup_view = select_popup_.view();
if (popup_view.is_null())
return;
- view_.SetAnchorRect(popup_view,
+ view->SetAnchorRect(popup_view,
gfx::ScaleRect(gfx::RectF(bounds), page_scale_));
Java_ContentViewCore_showSelectPopup(
env, j_obj, popup_view, reinterpret_cast<intptr_t>(frame), items_array,
@@ -656,8 +656,6 @@ void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
if (!view)
return;
- view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
-
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
@@ -736,14 +734,14 @@ gfx::Size ContentViewCoreImpl::GetViewSizeWithOSKHidden() const {
Java_ContentViewCore_getViewportHeightWithOSKHiddenPix(env, j_obj));
gfx::Size size_dip = gfx::ScaleToCeiledSize(size_pix, 1.0f / dpi_scale());
- if (DoTopControlsShrinkBlinkSize())
+ if (DoBrowserControlsShrinkBlinkSize())
size_dip.Enlarge(0, -GetTopControlsHeightDip());
return size_dip;
}
gfx::Size ContentViewCoreImpl::GetViewSize() const {
gfx::Size size = GetViewportSizeDip();
- if (DoTopControlsShrinkBlinkSize())
+ if (DoBrowserControlsShrinkBlinkSize())
size.Enlarge(0, -GetTopControlsHeightDip() - GetBottomControlsHeightDip());
return size;
}
@@ -787,12 +785,12 @@ gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
return gfx::ScaleToCeiledSize(GetViewportSizePix(), 1.0f / dpi_scale());
}
-bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
+bool ContentViewCoreImpl::DoBrowserControlsShrinkBlinkSize() const {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
return false;
- return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj);
+ return Java_ContentViewCore_doBrowserControlsShrinkBlinkSize(env, j_obj);
}
float ContentViewCoreImpl::GetTopControlsHeightDip() const {
@@ -803,6 +801,15 @@ float ContentViewCoreImpl::GetBottomControlsHeightDip() const {
return GetBottomControlsHeightPix() / dpi_scale();
}
+void ContentViewCoreImpl::SendScreenRectsAndResizeWidget() {
+ RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+ if (view) {
+ // |SendScreenRects()| indirectly calls GetViewSize() that asks Java layer.
+ web_contents_->SendScreenRects();
+ view->WasResized();
+ }
+}
+
void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
if (!web_contents_)
return;
@@ -824,11 +831,11 @@ void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
}
ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
- return view_.GetWindowAndroid();
+ return GetViewAndroid()->GetWindowAndroid();
}
-ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() {
- return &view_;
+ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
+ return web_contents_->GetView()->GetNativeView();
}
@@ -868,6 +875,16 @@ void ContentViewCoreImpl::SetFocus(JNIEnv* env,
SetFocusInternal(focused);
}
+void ContentViewCoreImpl::SetDIPScale(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jfloat dpi_scale) {
+ if (dpi_scale_ == dpi_scale)
+ return;
+
+ dpi_scale_ = dpi_scale;
+ SendScreenRectsAndResizeWidget();
+}
+
void ContentViewCoreImpl::SetFocusInternal(bool focused) {
if (!GetRenderWidgetHostViewAndroid())
return;
@@ -883,6 +900,7 @@ void ContentViewCoreImpl::SendOrientationChangeEvent(
const JavaParamRef<jobject>& obj,
jint orientation) {
if (device_orientation_ != orientation) {
+ base::RecordAction(base::UserMetricsAction("ScreenOrientationChange"));
device_orientation_ = orientation;
SendOrientationChangeEventInternal();
}
@@ -923,7 +941,7 @@ jboolean ContentViewCoreImpl::OnTouchEvent(
if (!rwhv)
return false;
- ui::MotionEventAndroid::Pointer pointer0(pointer_id_0,
+ MotionEventAndroid::Pointer pointer0(pointer_id_0,
pos_x_0,
pos_y_0,
touch_major_0,
@@ -931,7 +949,7 @@ jboolean ContentViewCoreImpl::OnTouchEvent(
orientation_0,
tilt_0,
android_tool_type_0);
- ui::MotionEventAndroid::Pointer pointer1(pointer_id_1,
+ MotionEventAndroid::Pointer pointer1(pointer_id_1,
pos_x_1,
pos_y_1,
touch_major_1,
@@ -939,7 +957,7 @@ jboolean ContentViewCoreImpl::OnTouchEvent(
orientation_1,
tilt_1,
android_tool_type_1);
- ui::MotionEventAndroid event(1.f / dpi_scale(),
+ MotionEventAndroid event(1.f / dpi_scale(),
env,
motion_event,
time_ms,
@@ -951,31 +969,63 @@ jboolean ContentViewCoreImpl::OnTouchEvent(
android_meta_state,
raw_pos_x - pos_x_0,
raw_pos_y - pos_y_0,
- pointer0,
- pointer1);
+ &pointer0,
+ &pointer1);
+
+ RecordToolTypeForActionDown(event);
return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
: rwhv->OnTouchEvent(event);
}
-jboolean ContentViewCoreImpl::SendMouseMoveEvent(
+jboolean ContentViewCoreImpl::SendMouseEvent(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong time_ms,
+ jint android_action,
jfloat x,
jfloat y,
- jint tool_type) {
+ jint pointer_id,
+ jfloat pressure,
+ jfloat orientation,
+ jfloat tilt,
+ jint android_changed_button,
+ jint android_button_state,
+ jint android_meta_state,
+ jint android_tool_type) {
+
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (!rwhv)
return false;
- blink::WebMouseEvent event = WebMouseEventBuilder::Build(
- WebInputEvent::MouseMove,
- blink::WebMouseEvent::Button::NoButton,
- time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1,
- ui::ToWebPointerType(static_cast<ui::MotionEvent::ToolType>(tool_type)));
+ // Construct a motion_event object minimally, only to convert the raw
+ // parameters to ui::MotionEvent values. Since we used only the cached values
+ // at index=0, it is okay to even pass a null event to the constructor.
+ MotionEventAndroid::Pointer pointer0(
+ pointer_id, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */,
+ orientation, tilt, android_tool_type);
+
+ MotionEventAndroid motion_event(1.f / dpi_scale(),
+ env,
+ nullptr /* event */,
+ time_ms,
+ android_action,
+ 1 /* pointer_count */,
+ 0 /* history_size */,
+ 0 /* action_index */,
+ android_button_state,
+ android_meta_state,
+ 0 /* raw_offset_x_pixels */,
+ 0 /* raw_offset_y_pixels */,
+ &pointer0,
+ nullptr);
+
+ RecordToolTypeForActionDown(motion_event);
+
+ // Note: This relies on identical button enum values in MotionEvent and
+ // MotionEventAndroid.
+ rwhv->SendMouseEvent(motion_event, android_changed_button);
- rwhv->SendMouseEvent(event);
return true;
}
@@ -1167,13 +1217,6 @@ void ContentViewCoreImpl::PinchBy(JNIEnv* env,
SendGestureEvent(event);
}
-void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->DismissTextHandles();
-}
-
void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
@@ -1236,16 +1279,12 @@ void ContentViewCoreImpl::RemoveJavascriptInterface(
void ContentViewCoreImpl::WasResized(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
- RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
gfx::Size physical_size(
Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
- view_.GetLayer()->SetBounds(physical_size);
+ GetViewAndroid()->GetLayer()->SetBounds(physical_size);
- if (view) {
- web_contents_->SendScreenRects();
- view->WasResized();
- }
+ SendScreenRectsAndResizeWidget();
}
long ContentViewCoreImpl::GetNativeImeAdapter(
@@ -1367,7 +1406,7 @@ void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (rwhv)
- rwhv->UpdateScreenInfo(&view_);
+ rwhv->UpdateScreenInfo(GetViewAndroid());
static_cast<WebContentsImpl*>(web_contents())->
screen_orientation_dispatcher_host()->OnOrientationChange();
@@ -1550,15 +1589,26 @@ void ContentViewCoreImpl::PullReset() {
// This is called for each ContentView.
jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& web_contents,
- const JavaParamRef<jobject>& view_android_delegate,
- jlong window_android,
+ const JavaParamRef<jobject>& jweb_contents,
+ const JavaParamRef<jobject>& jview_android_delegate,
+ jlong jwindow_android,
+ jfloat dipScale,
const JavaParamRef<jobject>& retained_objects_set) {
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromJavaWebContents(jweb_contents));
+ CHECK(web_contents) <<
+ "A ContentViewCoreImpl should be created with a valid WebContents.";
+ ui::ViewAndroid* view_android = web_contents->GetView()->GetNativeView();
+ view_android->SetDelegate(jview_android_delegate);
+
+ ui::WindowAndroid* window_android =
+ reinterpret_cast<ui::WindowAndroid*>(jwindow_android);
+ DCHECK(window_android);
+ window_android->AddChild(view_android);
+
+ // TODO: pass dipScale.
ContentViewCoreImpl* view = new ContentViewCoreImpl(
- env, obj, WebContents::FromJavaWebContents(web_contents),
- view_android_delegate,
- reinterpret_cast<ui::WindowAndroid*>(window_android),
- retained_objects_set);
+ env, obj, web_contents, dipScale, retained_objects_set);
return reinterpret_cast<intptr_t>(view);
}
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index 40c26a53c01..79bb54589ec 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -22,7 +22,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/web_contents_observer.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/android/overscroll_refresh.h"
#include "ui/android/view_android.h"
#include "ui/gfx/geometry/rect.h"
@@ -30,10 +30,6 @@
#include "ui/gfx/selection_bound.h"
#include "url/gurl.h"
-namespace cc {
-struct ViewportSelectionBound;
-}
-
namespace ui {
class WindowAndroid;
}
@@ -54,8 +50,7 @@ class ContentViewCoreImpl : public ContentViewCore,
JNIEnv* env,
const base::android::JavaRef<jobject>& obj,
WebContents* web_contents,
- const base::android::JavaRef<jobject>& view_android_delegate,
- ui::WindowAndroid* window_android,
+ float dpi_scale,
const base::android::JavaRef<jobject>& java_bridge_retained_object_set);
// ContentViewCore implementation.
@@ -63,7 +58,6 @@ class ContentViewCoreImpl : public ContentViewCore,
WebContents* GetWebContents() const override;
ui::WindowAndroid* GetWindowAndroid() const override;
void ShowPastePopup(int x, int y) override;
- void PauseOrResumeGeolocation(bool should_pause) override;
void AddObserver(ContentViewCoreImplObserver* observer);
void RemoveObserver(ContentViewCoreImplObserver* observer);
@@ -128,12 +122,20 @@ class ContentViewCoreImpl : public ContentViewCore,
jint android_button_state,
jint android_meta_state,
jboolean is_touch_handle_event);
- jboolean SendMouseMoveEvent(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jlong time_ms,
- jfloat x,
- jfloat y,
- jint tool_type);
+ jboolean SendMouseEvent(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jint android_action,
+ jfloat x,
+ jfloat y,
+ jint pointer_id,
+ jfloat pressure,
+ jfloat orientation,
+ jfloat tilt,
+ jint android_changed_button,
+ jint android_button_state,
+ jint android_meta_state,
+ jint tool_type);
jboolean SendMouseWheelEvent(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong time_ms,
@@ -200,8 +202,6 @@ class ContentViewCoreImpl : public ContentViewCore,
jfloat x,
jfloat y,
jfloat delta);
- void DismissTextHandles(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
void SetTextHandlesTemporarilyHidden(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -224,6 +224,10 @@ class ContentViewCoreImpl : public ContentViewCore,
const base::android::JavaParamRef<jobject>& obj,
jboolean focused);
+ void SetDIPScale(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jfloat dipScale);
+
jint GetBackgroundColor(JNIEnv* env, jobject obj);
void SetAllowJavascriptInterfacesInspection(
JNIEnv* env,
@@ -378,7 +382,7 @@ class ContentViewCoreImpl : public ContentViewCore,
gfx::Size GetPhysicalBackingSize() const;
gfx::Size GetViewportSizeDip() const;
- bool DoTopControlsShrinkBlinkSize() const;
+ bool DoBrowserControlsShrinkBlinkSize() const;
float GetTopControlsHeightDip() const;
float GetBottomControlsHeightDip() const;
@@ -389,7 +393,7 @@ class ContentViewCoreImpl : public ContentViewCore,
void OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip);
- ui::ViewAndroid* GetViewAndroid();
+ ui::ViewAndroid* GetViewAndroid() const;
private:
class ContentViewUserData;
@@ -414,6 +418,7 @@ class ContentViewCoreImpl : public ContentViewCore,
// --------------------------------------------------------------------------
void InitWebContents();
+ void SendScreenRectsAndResizeWidget();
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
@@ -442,8 +447,6 @@ class ContentViewCoreImpl : public ContentViewCore,
// Select popup view
ui::ViewAndroid::ScopedAnchorView select_popup_;
- ui::ViewAndroid view_;
-
// Reference to the current WebContents used to determine how and what to
// display in the ContentViewCore.
WebContentsImpl* web_contents_;
@@ -452,7 +455,7 @@ class ContentViewCoreImpl : public ContentViewCore,
float page_scale_;
// Device scale factor.
- const float dpi_scale_;
+ float dpi_scale_;
// Observer to notify of lifecyle changes.
base::ObserverList<ContentViewCoreImplObserver> observer_list_;
diff --git a/chromium/content/browser/android/content_view_statics.cc b/chromium/content/browser/android/content_view_statics.cc
index 81c3e351a82..b0f43af4262 100644
--- a/chromium/content/browser/android/content_view_statics.cc
+++ b/chromium/content/browser/android/content_view_statics.cc
@@ -11,6 +11,7 @@
#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/android/address_parser.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_process_host.h"
@@ -60,7 +61,7 @@ class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
!i.IsAtEnd(); i.Advance()) {
content::RenderProcessHost* host = i.GetCurrentValue();
host->AddObserver(this);
- host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(true));
+ host->GetRendererInterface()->SetWebKitSharedTimersSuspended(true);
suspended_processes_.push_back(host->GetID());
}
}
@@ -73,7 +74,7 @@ class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
content::RenderProcessHost::FromID(*it);
DCHECK(host);
host->RemoveObserver(this);
- host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(false));
+ host->GetRendererInterface()->SetWebKitSharedTimersSuspended(false);
}
suspended_processes_.clear();
}
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index 07d521084a9..0184ebc5e83 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -16,7 +16,6 @@
namespace content {
-class ContentViewCore;
class RenderViewHost;
struct DateTimeSuggestion;
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.h b/chromium/content/browser/android/interstitial_page_delegate_android.h
index dcc92ce94d6..3c136298934 100644
--- a/chromium/content/browser/android/interstitial_page_delegate_android.h
+++ b/chromium/content/browser/android/interstitial_page_delegate_android.h
@@ -17,7 +17,6 @@
namespace content {
class InterstitialPage;
-class WebContents;
// Native counterpart that allows interstitial pages to be constructed and
// managed from Java.
diff --git a/chromium/content/browser/android/java/gin_java_bound_object.cc b/chromium/content/browser/android/java/gin_java_bound_object.cc
index d281f8902b0..706f81e02d8 100644
--- a/chromium/content/browser/android/java/gin_java_bound_object.cc
+++ b/chromium/content/browser/android/java/gin_java_bound_object.cc
@@ -183,8 +183,8 @@ void GinJavaBoundObject::EnsureMethodsAreSetUp() {
continue;
}
- JavaMethod* method = new JavaMethod(java_method);
- methods_.insert(std::make_pair(method->name(), make_linked_ptr(method)));
+ std::unique_ptr<JavaMethod> method(new JavaMethod(java_method));
+ methods_.insert(std::make_pair(method->name(), std::move(method)));
}
}
diff --git a/chromium/content/browser/android/java/gin_java_bound_object.h b/chromium/content/browser/android/java/gin_java_bound_object.h
index 735e14a7b71..7c23c0eee88 100644
--- a/chromium/content/browser/android/java/gin_java_bound_object.h
+++ b/chromium/content/browser/android/java/gin_java_bound_object.h
@@ -9,11 +9,11 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
#include "content/browser/android/java/java_method.h"
@@ -79,7 +79,7 @@ class GinJavaBoundObject
std::set<int32_t> holders_;
// The following fields are accessed on the background thread.
- typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
+ using JavaMethodMap = std::multimap<std::string, std::unique_ptr<JavaMethod>>;
JavaMethodMap methods_;
jmethodID object_get_class_method_id_;
bool are_methods_set_up_;
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 736d1dde003..7338d65b611 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
@@ -374,7 +374,7 @@ void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
return;
JavaObjectWeakGlobalRef ref =
RemoveHolderAndAdvanceLocked(routing_id, &iter);
- if (!ref.is_empty()) {
+ if (!ref.is_uninitialized()) {
RemoveFromRetainedObjectSetLocked(ref);
}
}
diff --git a/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc b/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc
index 9c9cc09bdeb..a2e73ef2d69 100644
--- a/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc
+++ b/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc
@@ -100,7 +100,7 @@ bool GinJavaMethodInvocationHelper::AppendObjectRef(
if (iter == object_refs_.end()) {
JavaObjectWeakGlobalRef object_ref(
dispatcher->GetObjectWeakRef(object_id));
- if (!object_ref.is_empty()) {
+ if (!object_ref.is_uninitialized()) {
object_refs_.insert(std::make_pair(object_id, object_ref));
}
}
diff --git a/chromium/content/browser/android/java_interfaces_impl.cc b/chromium/content/browser/android/java_interfaces_impl.cc
index df2d8d63fff..2cc2b5701b8 100644
--- a/chromium/content/browser/android/java_interfaces_impl.cc
+++ b/chromium/content/browser/android/java_interfaces_impl.cc
@@ -15,7 +15,7 @@
#include "content/public/browser/web_contents.h"
#include "jni/InterfaceRegistrarImpl_jni.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
namespace content {
@@ -24,7 +24,7 @@ namespace {
class JavaInterfaceProviderHolder {
public:
JavaInterfaceProviderHolder() {
- shell::mojom::InterfaceProviderPtr provider;
+ service_manager::mojom::InterfaceProviderPtr provider;
JNIEnv* env = base::android::AttachCurrentThread();
Java_InterfaceRegistrarImpl_createInterfaceRegistryForContext(
env, mojo::GetProxy(&provider).PassMessagePipe().release().value(),
@@ -37,20 +37,22 @@ class JavaInterfaceProviderHolder {
return base::Singleton<JavaInterfaceProviderHolder>::get();
}
- shell::InterfaceProvider* GetJavaInterfaces() { return &interface_provider_; }
+ service_manager::InterfaceProvider* GetJavaInterfaces() {
+ return &interface_provider_;
+ }
private:
- shell::InterfaceProvider interface_provider_;
+ service_manager::InterfaceProvider interface_provider_;
};
} // namespace
-shell::InterfaceProvider* GetGlobalJavaInterfaces() {
+service_manager::InterfaceProvider* GetGlobalJavaInterfaces() {
return JavaInterfaceProviderHolder::GetInstance()->GetJavaInterfaces();
}
void BindInterfaceRegistryForWebContents(
- shell::mojom::InterfaceProviderRequest request,
+ service_manager::mojom::InterfaceProviderRequest request,
WebContents* web_contents) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_InterfaceRegistrarImpl_createInterfaceRegistryForWebContents(
diff --git a/chromium/content/browser/android/java_interfaces_impl.h b/chromium/content/browser/android/java_interfaces_impl.h
index e49ddcd24b9..f78c063d981 100644
--- a/chromium/content/browser/android/java_interfaces_impl.h
+++ b/chromium/content/browser/android/java_interfaces_impl.h
@@ -6,13 +6,13 @@
#define CONTENT_BROWSER_ANDROID_JAVA_INTERFACES_IMPL_H_
#include "content/public/browser/android/java_interfaces.h"
-#include "services/shell/public/interfaces/interface_provider.mojom.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
namespace content {
class WebContents;
void BindInterfaceRegistryForWebContents(
- shell::mojom::InterfaceProviderRequest request,
+ service_manager::mojom::InterfaceProviderRequest request,
WebContents* web_contents);
} // namespace content
diff --git a/chromium/content/browser/android/overscroll_controller_android.cc b/chromium/content/browser/android/overscroll_controller_android.cc
index b60f302c1b5..6e92d182c8a 100644
--- a/chromium/content/browser/android/overscroll_controller_android.cc
+++ b/chromium/content/browser/android/overscroll_controller_android.cc
@@ -13,7 +13,7 @@
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/android/edge_effect.h"
#include "ui/android/edge_effect_l.h"
#include "ui/android/resources/resource_manager.h"
diff --git a/chromium/content/browser/android/synchronous_compositor_browser_filter.cc b/chromium/content/browser/android/synchronous_compositor_browser_filter.cc
new file mode 100644
index 00000000000..6775f04c879
--- /dev/null
+++ b/chromium/content/browser/android/synchronous_compositor_browser_filter.cc
@@ -0,0 +1,240 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/synchronous_compositor_browser_filter.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
+#include "base/optional.h"
+#include "base/stl_util.h"
+#include "content/browser/android/synchronous_compositor_host.h"
+#include "content/browser/bad_message.h"
+#include "content/common/android/sync_compositor_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "ui/android/window_android.h"
+
+namespace content {
+
+SynchronousCompositorBrowserFilter::SynchronousCompositorBrowserFilter(
+ int process_id)
+ : BrowserMessageFilter(SyncCompositorMsgStart),
+ render_process_host_(RenderProcessHost::FromID(process_id)) {
+ DCHECK(render_process_host_);
+}
+
+SynchronousCompositorBrowserFilter::~SynchronousCompositorBrowserFilter() {
+ DCHECK(compositor_host_pending_renderer_state_.empty());
+ DCHECK(future_map_.empty());
+}
+
+void SynchronousCompositorBrowserFilter::SyncStateAfterVSync(
+ ui::WindowAndroid* window_android,
+ SynchronousCompositorHost* compositor_host) {
+ DCHECK(!window_android_in_vsync_ ||
+ window_android_in_vsync_ == window_android)
+ << !!window_android_in_vsync_;
+ DCHECK(compositor_host);
+ DCHECK(!base::ContainsValue(compositor_host_pending_renderer_state_,
+ compositor_host));
+ compositor_host_pending_renderer_state_.push_back(compositor_host);
+ if (window_android_in_vsync_)
+ return;
+ window_android_in_vsync_ = window_android;
+ window_android_in_vsync_->AddObserver(this);
+}
+
+bool SynchronousCompositorBrowserFilter::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorBrowserFilter, message)
+ IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
+ ReceiveFrame(message))
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool SynchronousCompositorBrowserFilter::ReceiveFrame(
+ const IPC::Message& message) {
+ SyncCompositorHostMsg_ReturnFrame::Param param;
+ if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
+ return false;
+
+ int routing_id = message.routing_id();
+ scoped_refptr<SynchronousCompositor::FrameFuture> future;
+ {
+ base::AutoLock lock(future_map_lock_);
+ auto itr = future_map_.find(routing_id);
+ if (itr == future_map_.end() || itr->second.empty()) {
+ bad_message::ReceivedBadMessage(render_process_host_,
+ bad_message::SCO_INVALID_ARGUMENT);
+ return true;
+ }
+ future = std::move(itr->second.front());
+ DCHECK(future);
+ itr->second.pop_front();
+ if (itr->second.empty())
+ future_map_.erase(itr);
+ }
+
+ auto frame_ptr = base::MakeUnique<SynchronousCompositor::Frame>();
+ frame_ptr->compositor_frame_sink_id = std::get<0>(param);
+ base::Optional<cc::CompositorFrame>& compositor_frame = std::get<1>(param);
+ if (compositor_frame) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &SynchronousCompositorBrowserFilter::ProcessFrameMetadataOnUIThread,
+ this, routing_id,
+ base::Passed(compositor_frame->metadata.Clone())));
+ frame_ptr->frame.reset(new cc::CompositorFrame);
+ *frame_ptr->frame = std::move(*compositor_frame);
+ }
+ future->SetFrame(std::move(frame_ptr));
+ return true;
+}
+
+void SynchronousCompositorBrowserFilter::ProcessFrameMetadataOnUIThread(
+ int routing_id,
+ cc::CompositorFrameMetadata metadata) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto itr = hosts_.find(routing_id);
+ if (itr == hosts_.end())
+ return;
+ itr->second->UpdateFrameMetaData(std::move(metadata));
+}
+
+void SynchronousCompositorBrowserFilter::RegisterHost(
+ SynchronousCompositorHost* host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(host);
+ DCHECK(!base::ContainsKey(hosts_, host->routing_id()));
+ hosts_[host->routing_id()] = host;
+}
+
+void SynchronousCompositorBrowserFilter::UnregisterHost(
+ SynchronousCompositorHost* host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(host);
+ int routing_id = host->routing_id();
+ DCHECK(base::ContainsKey(hosts_, routing_id));
+ DCHECK_EQ(host, hosts_[routing_id]);
+ hosts_.erase(routing_id);
+}
+
+void SynchronousCompositorBrowserFilter::SetFrameFuture(
+ int routing_id,
+ scoped_refptr<SynchronousCompositor::FrameFuture> frame_future) {
+ DCHECK(frame_future);
+ base::AutoLock lock(future_map_lock_);
+ if (!filter_ready_) {
+ frame_future->SetFrame(nullptr);
+ return;
+ }
+
+ auto itr = future_map_.find(routing_id);
+ if (itr == future_map_.end()) {
+ auto emplace_result = future_map_.emplace(routing_id, FrameFutureQueue());
+ DCHECK(emplace_result.second);
+ itr = emplace_result.first;
+ }
+
+ // Allowing arbitrary number of pending futures can lead to increase in frame
+ // latency. Due to this, Android platform already ensures that here that there
+ // can be at most 2 pending frames. Here, we rely on Android to do the
+ // necessary blocking, which allows more parallelism without increasing
+ // latency. But DCHECK Android blocking is working.
+ DCHECK_LT(itr->second.size(), 2u);
+ itr->second.emplace_back(std::move(frame_future));
+}
+
+void SynchronousCompositorBrowserFilter::OnFilterAdded(IPC::Channel* channel) {
+ base::AutoLock lock(future_map_lock_);
+ filter_ready_ = true;
+}
+
+void SynchronousCompositorBrowserFilter::OnFilterRemoved() {
+ SignalAllFutures();
+}
+
+void SynchronousCompositorBrowserFilter::OnChannelClosing() {
+ SignalAllFutures();
+}
+
+void SynchronousCompositorBrowserFilter::SignalAllFutures() {
+ base::AutoLock lock(future_map_lock_);
+ for (auto& pair : future_map_) {
+ for (auto& future_ptr : pair.second) {
+ future_ptr->SetFrame(nullptr);
+ }
+ }
+ future_map_.clear();
+ filter_ready_ = false;
+}
+
+void SynchronousCompositorBrowserFilter::OnCompositingDidCommit() {
+ NOTREACHED();
+}
+
+void SynchronousCompositorBrowserFilter::OnRootWindowVisibilityChanged(
+ bool visible) {
+ NOTREACHED();
+}
+
+void SynchronousCompositorBrowserFilter::OnAttachCompositor() {
+ NOTREACHED();
+}
+
+void SynchronousCompositorBrowserFilter::OnDetachCompositor() {
+ NOTREACHED();
+}
+
+void SynchronousCompositorBrowserFilter::OnVSync(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) {
+ // This is called after DidSendBeginFrame for SynchronousCompositorHosts
+ // belonging to this WindowAndroid, since this is added as an Observer after
+ // the observer iteration has started.
+ DCHECK(window_android_in_vsync_);
+ window_android_in_vsync_->RemoveObserver(this);
+ window_android_in_vsync_ = nullptr;
+
+ std::vector<int> routing_ids;
+ routing_ids.reserve(compositor_host_pending_renderer_state_.size());
+ for (const auto host : compositor_host_pending_renderer_state_)
+ routing_ids.push_back(host->routing_id());
+
+ std::vector<SyncCompositorCommonRendererParams> params;
+ params.reserve(compositor_host_pending_renderer_state_.size());
+
+ if (!render_process_host_->Send(
+ new SyncCompositorMsg_SynchronizeRendererState(routing_ids,
+ &params))) {
+ return;
+ }
+
+ if (compositor_host_pending_renderer_state_.size() != params.size()) {
+ bad_message::ReceivedBadMessage(render_process_host_,
+ bad_message::SCO_INVALID_ARGUMENT);
+ return;
+ }
+
+ for (size_t i = 0; i < compositor_host_pending_renderer_state_.size(); ++i) {
+ compositor_host_pending_renderer_state_[i]->ProcessCommonParams(params[i]);
+ }
+ compositor_host_pending_renderer_state_.clear();
+}
+
+void SynchronousCompositorBrowserFilter::OnActivityStopped() {
+ NOTREACHED();
+}
+
+void SynchronousCompositorBrowserFilter::OnActivityStarted() {
+ NOTREACHED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_browser_filter.h b/chromium/content/browser/android/synchronous_compositor_browser_filter.h
new file mode 100644
index 00000000000..bd40f5e0531
--- /dev/null
+++ b/chromium/content/browser/android/synchronous_compositor_browser_filter.h
@@ -0,0 +1,91 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
+#define CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
+
+#include <deque>
+#include <map>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "cc/output/compositor_frame_metadata.h"
+#include "content/public/browser/android/synchronous_compositor.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "ui/android/window_android_observer.h"
+
+namespace ui {
+class WindowAndroid;
+}
+
+namespace content {
+
+class RenderProcessHost;
+class SynchronousCompositorHost;
+
+class SynchronousCompositorBrowserFilter : public ui::WindowAndroidObserver,
+ public BrowserMessageFilter {
+ public:
+ explicit SynchronousCompositorBrowserFilter(int process_id);
+
+ // WindowAndroidObserver overrides.
+ void OnCompositingDidCommit() override;
+ void OnRootWindowVisibilityChanged(bool visible) override;
+ void OnAttachCompositor() override;
+ void OnDetachCompositor() override;
+ void OnVSync(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) override;
+ void OnActivityStopped() override;
+ void OnActivityStarted() override;
+
+ // BrowserMessageFilter overrides.
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Channel* channel) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
+
+ void SyncStateAfterVSync(ui::WindowAndroid* window_android,
+ SynchronousCompositorHost* compositor_host);
+
+ // Calls from SynchronousCompositorHost.
+ void RegisterHost(SynchronousCompositorHost* host);
+ void UnregisterHost(SynchronousCompositorHost* host);
+ void SetFrameFuture(
+ int routing_id,
+ scoped_refptr<SynchronousCompositor::FrameFuture> frame_future);
+
+ private:
+ ~SynchronousCompositorBrowserFilter() override;
+
+ bool ReceiveFrame(const IPC::Message& message);
+ void ProcessFrameMetadataOnUIThread(int routing_id,
+ cc::CompositorFrameMetadata metadata);
+ void SignalAllFutures();
+
+ RenderProcessHost* const render_process_host_;
+
+ // For synchronizing renderer state after a vsync.
+ ui::WindowAndroid* window_android_in_vsync_ = nullptr;
+ std::vector<SynchronousCompositorHost*>
+ compositor_host_pending_renderer_state_;
+
+ // Only accessed on the UI thread. Note this is not a parallel map to
+ // |future_map_|.
+ std::map<int, SynchronousCompositorHost*> hosts_;
+
+ base::Lock future_map_lock_; // Protects fields below.
+ bool filter_ready_ = false;
+ using FrameFutureQueue =
+ std::deque<scoped_refptr<SynchronousCompositor::FrameFuture>>;
+ // This object is per renderer process, so routing_id is unique.
+ using FrameFutureMap = std::map<int, FrameFutureQueue>;
+ FrameFutureMap future_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorBrowserFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 19127cf328a..4f2e1f07ecc 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -11,9 +11,8 @@
#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/trace_event/trace_event_argument.h"
-#include "content/browser/android/synchronous_compositor_observer.h"
+#include "content/browser/android/synchronous_compositor_browser_filter.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#include "content/browser/web_contents/web_contents_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/android/sync_compositor_messages.h"
#include "content/common/android/sync_compositor_statics.h"
@@ -32,45 +31,26 @@
namespace content {
// static
-void SynchronousCompositor::SetClientForWebContents(
- WebContents* contents,
- SynchronousCompositorClient* client) {
- DCHECK(contents);
- DCHECK(client);
- WebContentsAndroid* web_contents_android =
- static_cast<WebContentsImpl*>(contents)->GetWebContentsAndroid();
- DCHECK(!web_contents_android->synchronous_compositor_client());
- web_contents_android->set_synchronous_compositor_client(client);
-}
-
-// static
std::unique_ptr<SynchronousCompositorHost> SynchronousCompositorHost::Create(
- RenderWidgetHostViewAndroid* rwhva,
- WebContents* web_contents) {
- DCHECK(web_contents);
- WebContentsAndroid* web_contents_android =
- static_cast<WebContentsImpl*>(web_contents)->GetWebContentsAndroid();
- if (!web_contents_android->synchronous_compositor_client())
+ RenderWidgetHostViewAndroid* rwhva) {
+ if (!rwhva->synchronous_compositor_client())
return nullptr; // Not using sync compositing.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
bool use_in_proc_software_draw =
command_line->HasSwitch(switches::kSingleProcess);
return base::WrapUnique(new SynchronousCompositorHost(
- rwhva, web_contents_android->synchronous_compositor_client(),
- use_in_proc_software_draw));
+ rwhva, use_in_proc_software_draw));
}
SynchronousCompositorHost::SynchronousCompositorHost(
RenderWidgetHostViewAndroid* rwhva,
- SynchronousCompositorClient* client,
bool use_in_proc_software_draw)
: rwhva_(rwhva),
- client_(client),
+ client_(rwhva->synchronous_compositor_client()),
ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
- rph_observer_(SynchronousCompositorObserver::GetOrCreateFor(process_id_)),
sender_(rwhva_->GetRenderWidgetHost()),
use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
bytes_limit_(0u),
@@ -83,6 +63,10 @@ SynchronousCompositorHost::SynchronousCompositorHost(
SynchronousCompositorHost::~SynchronousCompositorHost() {
client_->DidDestroyCompositor(this, process_id_, routing_id_);
+ if (registered_with_filter_) {
+ if (SynchronousCompositorBrowserFilter* filter = GetFilter())
+ filter->UnregisterHost(this);
+ }
}
bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
@@ -91,21 +75,40 @@ bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_CompositorFrameSinkCreated,
CompositorFrameSinkCreated)
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
- IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
- DemandDrawHwReceiveFrame(message))
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void SynchronousCompositorHost::DemandDrawHwAsync(
+scoped_refptr<SynchronousCompositor::FrameFuture>
+SynchronousCompositorHost::DemandDrawHwAsync(
const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) {
+ scoped_refptr<FrameFuture> frame_future = new FrameFuture();
+ if (compute_scroll_needs_synchronous_draw_) {
+ compute_scroll_needs_synchronous_draw_ = false;
+ auto frame_ptr = base::MakeUnique<Frame>();
+ *frame_ptr = DemandDrawHw(viewport_size, viewport_rect_for_tile_priority,
+ transform_for_tile_priority);
+ frame_future->SetFrame(std::move(frame_ptr));
+ return frame_future;
+ }
+
SyncCompositorDemandDrawHwParams params(viewport_size,
viewport_rect_for_tile_priority,
transform_for_tile_priority);
- sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
+ if (SynchronousCompositorBrowserFilter* filter = GetFilter()) {
+ if (!registered_with_filter_) {
+ filter->RegisterHost(this);
+ registered_with_filter_ = true;
+ }
+ filter->SetFrameFuture(routing_id_, frame_future);
+ sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
+ } else {
+ frame_future->SetFrame(nullptr);
+ }
+ return frame_future;
}
SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
@@ -116,7 +119,7 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
viewport_rect_for_tile_priority,
transform_for_tile_priority);
uint32_t compositor_frame_sink_id;
- cc::CompositorFrame compositor_frame;
+ base::Optional<cc::CompositorFrame> compositor_frame;
SyncCompositorCommonRendererParams common_renderer_params;
if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
@@ -127,46 +130,14 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
ProcessCommonParams(common_renderer_params);
- return ProcessHardwareFrame(compositor_frame_sink_id,
- std::move(compositor_frame));
-}
-
-bool SynchronousCompositorHost::DemandDrawHwReceiveFrame(
- const IPC::Message& message) {
- SyncCompositorHostMsg_ReturnFrame::Param param;
- if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
- return false;
- uint32_t compositor_frame_sink_id = std::get<0>(param);
- cc::CompositorFrame compositor_frame = std::move(std::get<1>(param));
- scoped_refptr<SynchronousCompositor::FrameFuture> frame_future =
- new FrameFuture();
- SynchronousCompositor::Frame frame = ProcessHardwareFrame(
- compositor_frame_sink_id, std::move(compositor_frame));
- if (!frame.frame)
- return true;
- std::unique_ptr<SynchronousCompositor::Frame> frame_ptr =
- base::MakeUnique<SynchronousCompositor::Frame>();
- frame_ptr->frame = std::move(frame.frame);
- frame_ptr->compositor_frame_sink_id = frame.compositor_frame_sink_id;
- frame_future->setFrame(std::move(frame_ptr));
- client_->OnDrawHardwareProcessFrameFuture(std::move(frame_future));
- return true;
-}
+ if (!compositor_frame)
+ return SynchronousCompositor::Frame();
-SynchronousCompositor::Frame SynchronousCompositorHost::ProcessHardwareFrame(
- uint32_t compositor_frame_sink_id,
- cc::CompositorFrame compositor_frame) {
SynchronousCompositor::Frame frame;
frame.frame.reset(new cc::CompositorFrame);
frame.compositor_frame_sink_id = compositor_frame_sink_id;
- *frame.frame = std::move(compositor_frame);
- if (!frame.frame->delegated_frame_data) {
- // This can happen if compositor did not swap in this draw.
- frame.frame.reset();
- }
- if (frame.frame) {
- UpdateFrameMetaData(frame.frame->metadata.Clone());
- }
+ *frame.frame = std::move(*compositor_frame);
+ UpdateFrameMetaData(frame.frame->metadata.Clone());
return frame;
}
@@ -175,6 +146,12 @@ void SynchronousCompositorHost::UpdateFrameMetaData(
rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
}
+SynchronousCompositorBrowserFilter* SynchronousCompositorHost::GetFilter() {
+ return static_cast<RenderProcessHostImpl*>(
+ rwhva_->GetRenderWidgetHost()->GetProcess())
+ ->synchronous_compositor_filter();
+}
+
namespace {
class ScopedSetSkCanvas {
@@ -376,6 +353,7 @@ void SynchronousCompositorHost::OnComputeScroll(
SyncCompositorCommonRendererParams common_renderer_params;
sender_->Send(
new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
+ compute_scroll_needs_synchronous_draw_ = true;
}
void SynchronousCompositorHost::DidOverscroll(
@@ -387,7 +365,9 @@ void SynchronousCompositorHost::DidOverscroll(
void SynchronousCompositorHost::DidSendBeginFrame(
ui::WindowAndroid* window_android) {
- rph_observer_->SyncStateAfterVSync(window_android, this);
+ compute_scroll_needs_synchronous_draw_ = false;
+ if (SynchronousCompositorBrowserFilter* filter = GetFilter())
+ filter->SyncStateAfterVSync(window_android, this);
}
void SynchronousCompositorHost::CompositorFrameSinkCreated() {
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 657cf394fcd..9d232c5c652 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -25,14 +25,6 @@ class Message;
class Sender;
}
-namespace blink {
-class WebInputEvent;
-}
-
-namespace cc {
-struct BeginFrameArgs;
-}
-
namespace ui {
class WindowAndroid;
struct DidOverscrollParams;
@@ -42,15 +34,14 @@ namespace content {
class RenderWidgetHostViewAndroid;
class SynchronousCompositorClient;
-class SynchronousCompositorObserver;
+class SynchronousCompositorBrowserFilter;
class WebContents;
struct SyncCompositorCommonRendererParams;
class SynchronousCompositorHost : public SynchronousCompositor {
public:
static std::unique_ptr<SynchronousCompositorHost> Create(
- RenderWidgetHostViewAndroid* rwhva,
- WebContents* web_contents);
+ RenderWidgetHostViewAndroid* rwhva);
~SynchronousCompositorHost() override;
@@ -59,7 +50,7 @@ class SynchronousCompositorHost : public SynchronousCompositor {
const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override;
- void DemandDrawHwAsync(
+ scoped_refptr<FrameFuture> DemandDrawHwAsync(
const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override;
@@ -76,8 +67,9 @@ class SynchronousCompositorHost : public SynchronousCompositor {
void DidSendBeginFrame(ui::WindowAndroid* window_android);
bool OnMessageReceived(const IPC::Message& message);
- // Called by SynchronousCompositorObserver.
+ // Called by SynchronousCompositorBrowserFilter.
int routing_id() const { return routing_id_; }
+ void UpdateFrameMetaData(cc::CompositorFrameMetadata frame_metadata);
void ProcessCommonParams(const SyncCompositorCommonRendererParams& params);
SynchronousCompositorClient* client() { return client_; }
@@ -89,30 +81,29 @@ class SynchronousCompositorHost : public SynchronousCompositor {
friend class SynchronousCompositorBase;
SynchronousCompositorHost(RenderWidgetHostViewAndroid* rwhva,
- SynchronousCompositorClient* client,
bool use_in_proc_software_draw);
- void UpdateFrameMetaData(cc::CompositorFrameMetadata frame_metadata);
void CompositorFrameSinkCreated();
bool DemandDrawSwInProc(SkCanvas* canvas);
void SetSoftwareDrawSharedMemoryIfNeeded(size_t stride, size_t buffer_size);
void SendZeroMemory();
- SynchronousCompositor::Frame ProcessHardwareFrame(
- uint32_t compositor_frame_sink_id,
- cc::CompositorFrame compositor_frame);
- bool DemandDrawHwReceiveFrame(const IPC::Message& message);
+ SynchronousCompositorBrowserFilter* GetFilter();
RenderWidgetHostViewAndroid* const rwhva_;
SynchronousCompositorClient* const client_;
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
const int process_id_;
const int routing_id_;
- SynchronousCompositorObserver* const rph_observer_;
IPC::Sender* const sender_;
const bool use_in_process_zero_copy_software_draw_;
+ bool registered_with_filter_ = false;
+
size_t bytes_limit_;
std::unique_ptr<SharedMemoryWithSize> software_draw_shm_;
+ // Indicates the next draw needs to be synchronous
+ bool compute_scroll_needs_synchronous_draw_ = false;
+
// Updated by both renderer and browser.
gfx::ScrollOffset root_scroll_offset_;
diff --git a/chromium/content/browser/android/synchronous_compositor_observer.cc b/chromium/content/browser/android/synchronous_compositor_observer.cc
deleted file mode 100644
index bbf778510d8..00000000000
--- a/chromium/content/browser/android/synchronous_compositor_observer.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/synchronous_compositor_observer.h"
-
-#include <map>
-
-#include "base/lazy_instance.h"
-#include "base/stl_util.h"
-#include "content/browser/android/synchronous_compositor_host.h"
-#include "content/browser/bad_message.h"
-#include "content/common/android/sync_compositor_messages.h"
-#include "content/public/browser/render_process_host.h"
-#include "ui/android/window_android.h"
-
-namespace content {
-
-namespace {
-base::LazyInstance<std::map<int, SynchronousCompositorObserver*>> g_instances;
-}
-
-// static
-SynchronousCompositorObserver* SynchronousCompositorObserver::GetOrCreateFor(
- int process_id) {
- auto itr = g_instances.Get().find(process_id);
- if (itr != g_instances.Get().end())
- return itr->second;
- return new SynchronousCompositorObserver(process_id);
-}
-
-SynchronousCompositorObserver::SynchronousCompositorObserver(int process_id)
- : render_process_host_(RenderProcessHost::FromID(process_id)),
- window_android_in_vsync_(nullptr) {
- DCHECK(render_process_host_);
- DCHECK(!base::ContainsKey(g_instances.Get(), render_process_host_->GetID()));
- g_instances.Get()[render_process_host_->GetID()] = this;
- render_process_host_->AddObserver(this);
-}
-
-SynchronousCompositorObserver::~SynchronousCompositorObserver() {
- DCHECK(compositor_host_pending_renderer_state_.empty());
- DCHECK(base::ContainsKey(g_instances.Get(), render_process_host_->GetID()));
- DCHECK_EQ(this, g_instances.Get()[render_process_host_->GetID()]);
- render_process_host_->RemoveObserver(this);
- g_instances.Get().erase(render_process_host_->GetID());
-}
-
-void SynchronousCompositorObserver::RenderProcessHostDestroyed(
- RenderProcessHost* host) {
- DCHECK_EQ(render_process_host_, host);
- delete this;
-}
-
-void SynchronousCompositorObserver::SyncStateAfterVSync(
- ui::WindowAndroid* window_android,
- SynchronousCompositorHost* compositor_host) {
- DCHECK(!window_android_in_vsync_ ||
- window_android_in_vsync_ == window_android)
- << !!window_android_in_vsync_;
- DCHECK(compositor_host);
- DCHECK(!base::ContainsValue(compositor_host_pending_renderer_state_,
- compositor_host));
- compositor_host_pending_renderer_state_.push_back(compositor_host);
- if (window_android_in_vsync_)
- return;
- window_android_in_vsync_ = window_android;
- window_android_in_vsync_->AddObserver(this);
-}
-
-void SynchronousCompositorObserver::OnCompositingDidCommit() {
- NOTREACHED();
-}
-
-void SynchronousCompositorObserver::OnRootWindowVisibilityChanged(
- bool visible) {
- NOTREACHED();
-}
-
-void SynchronousCompositorObserver::OnAttachCompositor() {
- NOTREACHED();
-}
-
-void SynchronousCompositorObserver::OnDetachCompositor() {
- NOTREACHED();
-}
-
-void SynchronousCompositorObserver::OnVSync(base::TimeTicks frame_time,
- base::TimeDelta vsync_period) {
- // This is called after DidSendBeginFrame for SynchronousCompositorHosts
- // belonging to this WindowAndroid, since this is added as an Observer after
- // the observer iteration has started.
- DCHECK(window_android_in_vsync_);
- window_android_in_vsync_->RemoveObserver(this);
- window_android_in_vsync_ = nullptr;
-
- std::vector<int> routing_ids;
- routing_ids.reserve(compositor_host_pending_renderer_state_.size());
- for (const auto host : compositor_host_pending_renderer_state_)
- routing_ids.push_back(host->routing_id());
-
- std::vector<SyncCompositorCommonRendererParams> params;
- params.reserve(compositor_host_pending_renderer_state_.size());
-
- if (!render_process_host_->Send(
- new SyncCompositorMsg_SynchronizeRendererState(routing_ids,
- &params))) {
- return;
- }
-
- if (compositor_host_pending_renderer_state_.size() != params.size()) {
- bad_message::ReceivedBadMessage(render_process_host_,
- bad_message::SCO_INVALID_ARGUMENT);
- return;
- }
-
- for (size_t i = 0; i < compositor_host_pending_renderer_state_.size(); ++i) {
- compositor_host_pending_renderer_state_[i]->ProcessCommonParams(params[i]);
- }
- compositor_host_pending_renderer_state_.clear();
-}
-
-void SynchronousCompositorObserver::OnActivityStopped() {
- NOTREACHED();
-}
-
-void SynchronousCompositorObserver::OnActivityStarted() {
- NOTREACHED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_observer.h b/chromium/content/browser/android/synchronous_compositor_observer.h
deleted file mode 100644
index 864df1645be..00000000000
--- a/chromium/content/browser/android/synchronous_compositor_observer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_OBSERVER_H_
-#define CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_OBSERVER_H_
-
-#include <vector>
-
-#include "base/macros.h"
-#include "content/public/browser/render_process_host_observer.h"
-#include "ui/android/window_android_observer.h"
-
-namespace ui {
-class WindowAndroid;
-}
-
-namespace content {
-
-class SynchronousCompositorHost;
-
-// SynchronousCompositor class that's tied to the lifetime of a
-// RenderProcessHost. Responsible for its own lifetime.
-class SynchronousCompositorObserver : public RenderProcessHostObserver,
- public ui::WindowAndroidObserver {
- public:
- static SynchronousCompositorObserver* GetOrCreateFor(int process_id);
-
- // RenderProcessHostObserver overrides.
- void RenderProcessHostDestroyed(RenderProcessHost* host) override;
-
- // WindowAndroidObserver overrides.
- void OnCompositingDidCommit() override;
- void OnRootWindowVisibilityChanged(bool visible) override;
- void OnAttachCompositor() override;
- void OnDetachCompositor() override;
- void OnVSync(base::TimeTicks frame_time,
- base::TimeDelta vsync_period) override;
- void OnActivityStopped() override;
- void OnActivityStarted() override;
-
- void SyncStateAfterVSync(ui::WindowAndroid* window_android,
- SynchronousCompositorHost* compositor_host);
-
- private:
- explicit SynchronousCompositorObserver(int process_id);
- ~SynchronousCompositorObserver() override;
-
- RenderProcessHost* const render_process_host_;
-
- // For synchronizing renderer state after a vsync.
- ui::WindowAndroid* window_android_in_vsync_;
- std::vector<SynchronousCompositorHost*>
- compositor_host_pending_renderer_state_;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_OBSERVER_H_
diff --git a/chromium/content/browser/android/url_request_content_job.h b/chromium/content/browser/android/url_request_content_job.h
index 2f70b5dbbf1..f36f904cc7e 100644
--- a/chromium/content/browser/android/url_request_content_job.h
+++ b/chromium/content/browser/android/url_request_content_job.h
@@ -24,10 +24,6 @@ namespace base {
class TaskRunner;
}
-namespace file_util {
-struct FileInfo;
-}
-
namespace net {
class FileStream;
}
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index b9e23ac980b..34e72a96838 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -294,6 +294,18 @@ void WebContentsObserverProxy::DidFirstVisuallyNonEmptyPaint() {
Java_WebContentsObserverProxy_didFirstVisuallyNonEmptyPaint(env, obj);
}
+void WebContentsObserverProxy::WasShown() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(java_observer_);
+ Java_WebContentsObserverProxy_wasShown(env, obj);
+}
+
+void WebContentsObserverProxy::WasHidden() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(java_observer_);
+ Java_WebContentsObserverProxy_wasHidden(env, obj);
+}
+
void WebContentsObserverProxy::DidStartNavigationToPendingEntry(
const GURL& url,
ReloadType reload_type) {
@@ -306,22 +318,6 @@ void WebContentsObserverProxy::DidStartNavigationToPendingEntry(
jstring_url);
}
-void WebContentsObserverProxy::MediaSessionStateChanged(
- bool is_controllable,
- bool is_suspended,
- const base::Optional<MediaMetadata>& metadata) {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj(java_observer_);
- ScopedJavaLocalRef<jobject> j_metadata;
-
- if (metadata.has_value())
- j_metadata = MediaMetadataAndroid::CreateJavaObject(env, metadata.value());
-
- Java_WebContentsObserverProxy_mediaSessionStateChanged(
- env, obj, is_controllable, is_suspended, j_metadata);
-}
-
void WebContentsObserverProxy::SetToBaseURLForDataURLIfNeeded(
std::string* url) {
NavigationEntry* entry =
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.h b/chromium/content/browser/android/web_contents_observer_proxy.h
index 40fceb476e8..794f467a209 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.h
+++ b/chromium/content/browser/android/web_contents_observer_proxy.h
@@ -18,7 +18,6 @@
namespace content {
-class RenderViewHost;
class WebContents;
// Extends WebContentsObserver for providing a public Java API for some of the
@@ -53,6 +52,8 @@ class WebContentsObserverProxy : public WebContentsObserver {
const FrameNavigateParams& params) override;
void DocumentAvailableInMainFrame() override;
void DidFirstVisuallyNonEmptyPaint() override;
+ void WasShown() override;
+ void WasHidden() override;
void DidStartProvisionalLoadForFrame(RenderFrameHost* render_frame_host,
const GURL& validated_url,
bool is_error_page,
@@ -73,10 +74,6 @@ class WebContentsObserverProxy : public WebContentsObserver {
void DidStartNavigationToPendingEntry(
const GURL& url,
ReloadType reload_type) override;
- void MediaSessionStateChanged(
- bool is_controllable,
- bool is_suspended,
- const base::Optional<MediaMetadata>& metadata) override;
void SetToBaseURLForDataURLIfNeeded(std::string* url);
void DidFailLoadInternal(bool is_provisional_load,
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.cc b/chromium/content/browser/appcache/appcache_backend_impl.cc
index caa0dd5965b..7f29c3e97a7 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.cc
+++ b/chromium/content/browser/appcache/appcache_backend_impl.cc
@@ -4,7 +4,7 @@
#include "content/browser/appcache/appcache_backend_impl.h"
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_service_impl.h"
@@ -18,7 +18,7 @@ AppCacheBackendImpl::AppCacheBackendImpl()
}
AppCacheBackendImpl::~AppCacheBackendImpl() {
- base::STLDeleteValues(&hosts_);
+ hosts_.clear();
if (service_)
service_->UnregisterBackend(this);
}
@@ -37,19 +37,12 @@ bool AppCacheBackendImpl::RegisterHost(int id) {
if (GetHost(id))
return false;
- hosts_.insert(
- HostMap::value_type(id, new AppCacheHost(id, frontend_, service_)));
+ hosts_[id] = base::MakeUnique<AppCacheHost>(id, frontend_, service_);
return true;
}
bool AppCacheBackendImpl::UnregisterHost(int id) {
- HostMap::iterator found = hosts_.find(id);
- if (found == hosts_.end())
- return false;
-
- delete found->second;
- hosts_.erase(found);
- return true;
+ return hosts_.erase(id) > 0;
}
bool AppCacheBackendImpl::SetSpawningHostId(
@@ -145,35 +138,32 @@ void AppCacheBackendImpl::GetResourceList(
std::unique_ptr<AppCacheHost> AppCacheBackendImpl::TransferHostOut(
int host_id) {
- HostMap::iterator found = hosts_.find(host_id);
+ auto found = hosts_.find(host_id);
if (found == hosts_.end()) {
NOTREACHED();
return std::unique_ptr<AppCacheHost>();
}
- AppCacheHost* transferree = found->second;
+ std::unique_ptr<AppCacheHost> transferree = std::move(found->second);
// Put a new empty host in its place.
- found->second = new AppCacheHost(host_id, frontend_, service_);
+ found->second = base::MakeUnique<AppCacheHost>(host_id, frontend_, service_);
// We give up ownership.
transferree->PrepareForTransfer();
- return std::unique_ptr<AppCacheHost>(transferree);
+ return transferree;
}
void AppCacheBackendImpl::TransferHostIn(int new_host_id,
std::unique_ptr<AppCacheHost> host) {
- HostMap::iterator found = hosts_.find(new_host_id);
+ auto found = hosts_.find(new_host_id);
if (found == hosts_.end()) {
NOTREACHED();
return;
}
- delete found->second;
-
- // We take onwership.
host->CompleteTransfer(new_host_id, frontend_);
- found->second = host.release();
+ found->second = std::move(host);
}
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.h b/chromium/content/browser/appcache/appcache_backend_impl.h
index 4585b789038..e7f9b84eb28 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.h
+++ b/chromium/content/browser/appcache/appcache_backend_impl.h
@@ -53,11 +53,11 @@ class CONTENT_EXPORT AppCacheBackendImpl {
// Returns a pointer to a registered host. The backend retains ownership.
AppCacheHost* GetHost(int host_id) {
- HostMap::iterator it = hosts_.find(host_id);
- return (it != hosts_.end()) ? (it->second) : NULL;
+ auto it = hosts_.find(host_id);
+ return (it != hosts_.end()) ? (it->second.get()) : nullptr;
}
- typedef base::hash_map<int, AppCacheHost*> HostMap;
+ typedef base::hash_map<int, std::unique_ptr<AppCacheHost>> HostMap;
const HostMap& hosts() { return hosts_; }
// Methods to support cross site navigations. Hosts are transferred
@@ -71,6 +71,8 @@ class CONTENT_EXPORT AppCacheBackendImpl {
AppCacheFrontend* frontend_;
int process_id_;
HostMap hosts_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheBackendImpl);
};
} // namespace
diff --git a/chromium/content/browser/appcache/appcache_group.cc b/chromium/content/browser/appcache/appcache_group.cc
index 0e8f3c496da..573983eba6e 100644
--- a/chromium/content/browser/appcache/appcache_group.cc
+++ b/chromium/content/browser/appcache/appcache_group.cc
@@ -260,7 +260,8 @@ void AppCacheGroup::SetUpdateAppCacheStatus(UpdateAppCacheStatus status) {
// deletion by adding an extra ref in this scope (but only if we're not
// in our destructor).
scoped_refptr<AppCacheGroup> protect(is_in_dtor_ ? NULL : this);
- FOR_EACH_OBSERVER(UpdateObserver, observers_, OnUpdateComplete(this));
+ for (auto& observer : observers_)
+ observer.OnUpdateComplete(this);
if (!queued_updates_.empty())
ScheduleUpdateRestart(kUpdateRestartDelayMs);
}
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index 697b2bdf8d0..adcefe08f58 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -62,7 +62,8 @@ AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend,
AppCacheHost::~AppCacheHost() {
service_->RemoveObserver(this);
- FOR_EACH_OBSERVER(Observer, observers_, OnDestructionImminent(this));
+ for (auto& observer : observers_)
+ observer.OnDestructionImminent(this);
if (associated_cache_.get())
associated_cache_->UnassociateHost(this);
if (group_being_updated_.get())
@@ -453,7 +454,8 @@ void AppCacheHost::FinishCacheSelection(
else if (!pending_swap_cache_callback_.is_null())
DoPendingSwapCache();
- FOR_EACH_OBSERVER(Observer, observers_, OnCacheSelectionComplete(this));
+ for (auto& observer : observers_)
+ observer.OnCacheSelectionComplete(this);
}
void AppCacheHost::OnServiceReinitialized(
diff --git a/chromium/content/browser/appcache/appcache_quota_client.cc b/chromium/content/browser/appcache/appcache_quota_client.cc
index cff86402674..6edfd887762 100644
--- a/chromium/content/browser/appcache/appcache_quota_client.cc
+++ b/chromium/content/browser/appcache/appcache_quota_client.cc
@@ -184,7 +184,7 @@ void AppCacheQuotaClient::GetOriginsHelper(storage::StorageType type,
std::set<GURL> origins;
for (AppCacheStorage::UsageMap::const_iterator iter = map->begin();
iter != map->end(); ++iter) {
- if (opt_host.empty() || iter->first.host() == opt_host)
+ if (opt_host.empty() || iter->first.host_piece() == opt_host)
origins.insert(iter->first);
}
callback.Run(origins);
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index f8465303a5a..8367bc8b1f3 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -1002,7 +1002,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_TRUE(handler_->found_manifest_url_.is_empty());
EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
EXPECT_TRUE(host_->main_resource_blocked_);
- EXPECT_TRUE(host_->blocked_manifest_url_ == GURL("http://blah/manifest/"));
+ EXPECT_EQ(host_->blocked_manifest_url_, "http://blah/manifest/");
TestFinished();
}
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index fbc0027dc4b..2978f499307 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -12,8 +12,8 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_backend_impl.h"
@@ -51,12 +51,14 @@ class AppCacheServiceImpl::AsyncHelper
AsyncHelper(AppCacheServiceImpl* service,
const net::CompletionCallback& callback)
: service_(service), callback_(callback) {
- service_->pending_helpers_.insert(this);
+ service_->pending_helpers_[this] = base::WrapUnique(this);
}
~AsyncHelper() override {
- if (service_)
+ if (service_) {
+ service_->pending_helpers_[this].release();
service_->pending_helpers_.erase(this);
+ }
}
virtual void Start() = 0;
@@ -82,7 +84,7 @@ void AppCacheServiceImpl::AsyncHelper::Cancel() {
callback_.Reset();
}
service_->storage()->CancelDelegateCallbacks(this);
- service_ = NULL;
+ service_ = nullptr;
}
// DeleteHelper -------
@@ -397,11 +399,11 @@ AppCacheStorageReference::~AppCacheStorageReference() {}
AppCacheServiceImpl::AppCacheServiceImpl(
storage::QuotaManagerProxy* quota_manager_proxy)
- : appcache_policy_(NULL),
- quota_client_(NULL),
- handler_factory_(NULL),
+ : appcache_policy_(nullptr),
+ quota_client_(nullptr),
+ handler_factory_(nullptr),
quota_manager_proxy_(quota_manager_proxy),
- request_context_(NULL),
+ request_context_(nullptr),
force_keep_session_state_(false),
weak_factory_(this) {
if (quota_manager_proxy_.get()) {
@@ -412,10 +414,11 @@ AppCacheServiceImpl::AppCacheServiceImpl(
AppCacheServiceImpl::~AppCacheServiceImpl() {
DCHECK(backends_.empty());
- FOR_EACH_OBSERVER(Observer, observers_, OnServiceDestructionImminent(this));
- for (auto* helper : pending_helpers_)
- helper->Cancel();
- base::STLDeleteElements(&pending_helpers_);
+ for (auto& observer : observers_)
+ observer.OnServiceDestructionImminent(this);
+ for (auto& helper : pending_helpers_)
+ helper.first->Cancel();
+ pending_helpers_.clear();
if (quota_client_)
quota_client_->NotifyAppCacheDestroyed();
@@ -472,8 +475,8 @@ void AppCacheServiceImpl::Reinitialize() {
// defer deletion of the old storage object.
scoped_refptr<AppCacheStorageReference> old_storage_ref(
new AppCacheStorageReference(std::move(storage_)));
- FOR_EACH_OBSERVER(Observer, observers_,
- OnServiceReinitialized(old_storage_ref.get()));
+ for (auto& observer : observers_)
+ observer.OnServiceReinitialized(old_storage_ref.get());
Initialize(cache_directory_, db_thread_, cache_thread_);
}
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index 1fdc34836cb..ea78f6910e9 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -9,7 +9,6 @@
#include <map>
#include <memory>
-#include <set>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -195,8 +194,9 @@ class CONTENT_EXPORT AppCacheServiceImpl
class GetInfoHelper;
class CheckResponseHelper;
- typedef std::set<AsyncHelper*> PendingAsyncHelpers;
- typedef std::map<int, AppCacheBackendImpl*> BackendMap;
+ using PendingAsyncHelpers =
+ std::map<AsyncHelper*, std::unique_ptr<AsyncHelper>>;
+ using BackendMap = std::map<int, AppCacheBackendImpl*>;
void Reinitialize();
diff --git a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
index e29c372d0e7..a4418a563c4 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -9,13 +11,15 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache_database.h"
#include "content/browser/appcache/appcache_storage_impl.h"
#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/browser_thread_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/appcache_test_helper.h"
#include "net/url_request/url_request_context_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,9 +39,10 @@ const char kSessionOnlyManifest[] = "http://www.sessiononly.com/cache.manifest";
class MockURLRequestContextGetter : public net::URLRequestContextGetter {
public:
- MockURLRequestContextGetter(net::URLRequestContext* context,
- base::SingleThreadTaskRunner* task_runner)
- : context_(context), task_runner_(task_runner) {}
+ MockURLRequestContextGetter(
+ net::URLRequestContext* context,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : context_(context), task_runner_(std::move(task_runner)) {}
net::URLRequestContext* GetURLRequestContext() override { return context_; }
@@ -62,11 +67,7 @@ class ChromeAppCacheServiceTest : public testing::Test {
: kProtectedManifestURL(kProtectedManifest),
kNormalManifestURL(kNormalManifest),
kSessionOnlyManifestURL(kSessionOnlyManifest),
- file_thread_(BrowserThread::FILE, &message_loop_),
- file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
- &message_loop_),
- cache_thread_(BrowserThread::CACHE, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_) {}
+ thread_bundle_(TestBrowserThreadBundle::Options::IO_MAINLOOP) {}
protected:
scoped_refptr<ChromeAppCacheService> CreateAppCacheServiceImpl(
@@ -74,17 +75,13 @@ class ChromeAppCacheServiceTest : public testing::Test {
bool init_storage);
void InsertDataIntoAppCache(ChromeAppCacheService* appcache_service);
- base::MessageLoopForIO message_loop_;
base::ScopedTempDir temp_dir_;
const GURL kProtectedManifestURL;
const GURL kNormalManifestURL;
const GURL kSessionOnlyManifestURL;
private:
- BrowserThreadImpl file_thread_;
- BrowserThreadImpl file_user_blocking_thread_;
- BrowserThreadImpl cache_thread_;
- BrowserThreadImpl io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
TestBrowserContext browser_context_;
};
@@ -101,7 +98,7 @@ ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
scoped_refptr<MockURLRequestContextGetter> mock_request_context_getter =
new MockURLRequestContextGetter(
browser_context_.GetResourceContext()->GetRequestContext(),
- message_loop_.task_runner().get());
+ base::ThreadTaskRunnerHandle::Get());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
diff --git a/chromium/content/browser/background_sync/background_sync_context.cc b/chromium/content/browser/background_sync/background_sync_context.cc
index 6a5166a048e..c1b920fbe71 100644
--- a/chromium/content/browser/background_sync/background_sync_context.cc
+++ b/chromium/content/browser/background_sync/background_sync_context.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
@@ -55,10 +56,9 @@ void BackgroundSyncContext::CreateService(
void BackgroundSyncContext::ServiceHadConnectionError(
BackgroundSyncServiceImpl* service) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(base::ContainsValue(services_, service));
+ DCHECK(base::ContainsKey(services_, service));
services_.erase(service);
- delete service;
}
BackgroundSyncManager* BackgroundSyncContext::background_sync_manager() const {
@@ -86,13 +86,15 @@ void BackgroundSyncContext::CreateServiceOnIOThread(
mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(background_sync_manager_);
- services_.insert(new BackgroundSyncServiceImpl(this, std::move(request)));
+ BackgroundSyncServiceImpl* service =
+ new BackgroundSyncServiceImpl(this, std::move(request));
+ services_[service] = base::WrapUnique(service);
}
void BackgroundSyncContext::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::STLDeleteElements(&services_);
+ services_.clear();
background_sync_manager_.reset();
}
diff --git a/chromium/content/browser/background_sync/background_sync_context.h b/chromium/content/browser/background_sync/background_sync_context.h
index 9f2c986c15d..4d3ecf32a07 100644
--- a/chromium/content/browser/background_sync/background_sync_context.h
+++ b/chromium/content/browser/background_sync/background_sync_context.h
@@ -5,8 +5,8 @@
#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_CONTEXT_H_
#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_CONTEXT_H_
+#include <map>
#include <memory>
-#include <set>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -70,7 +70,9 @@ class CONTENT_EXPORT BackgroundSyncContext
// The services are owned by this. They're either deleted
// during ShutdownOnIO or when the channel is closed via
// ServiceHadConnectionError. Only accessed on the IO thread.
- std::set<BackgroundSyncServiceImpl*> services_;
+ std::map<BackgroundSyncServiceImpl*,
+ std::unique_ptr<BackgroundSyncServiceImpl>>
+ services_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncContext);
};
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 a5c8b14e366..3127778d2ec 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -138,7 +138,7 @@ class BackgroundSyncManagerTest : public testing::Test {
storage_partition_impl_.reset(new StoragePartitionImpl(
helper_->browser_context(), base::FilePath(), nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr));
+ nullptr, nullptr, nullptr));
helper_->context_wrapper()->set_storage_partition(
storage_partition_impl_.get());
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
index a7f1e4681be..a6874d68c6f 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
@@ -135,7 +135,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
storage_partition_impl_.reset(new StoragePartitionImpl(
embedded_worker_helper_->browser_context(), base::FilePath(), nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr));
+ nullptr, nullptr, nullptr, nullptr, nullptr));
embedded_worker_helper_->context_wrapper()->set_storage_partition(
storage_partition_impl_.get());
}
@@ -186,7 +186,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
background_sync_context_->CreateService(std::move(service_request));
base::RunLoop().RunUntilIdle();
- service_impl_ = *background_sync_context_->services_.begin();
+ service_impl_ = background_sync_context_->services_.begin()->first;
ASSERT_TRUE(service_impl_);
}
diff --git a/chromium/content/browser/bad_message.cc b/chromium/content/browser/bad_message.cc
index 4ef20f86cd8..487742be1a8 100644
--- a/chromium/content/browser/bad_message.cc
+++ b/chromium/content/browser/bad_message.cc
@@ -8,7 +8,7 @@
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
-#include "base/metrics/sparse_histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index 9fd5bff5569..eb8150496b3 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -121,7 +121,7 @@ enum BadMessageReason {
RDH_INVALID_URL = 97,
BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED = 98,
RFH_OWNER_PROPERTY = 99,
- BDH_EMPTY_OR_INVALID_FILTERS = 100,
+ BDH_EMPTY_OR_INVALID_FILTERS = 100, // obsolete; no longer used
WC_CONTENT_WITH_CERT_ERRORS_BAD_SECURITY_INFO = 101, // obsolete; not used
RFMF_RENDERER_FAKED_ITS_OWN_DEATH = 102,
DWNLD_INVALID_SAVABLE_RESOURCE_LINKS_RESPONSE = 103,
@@ -162,6 +162,24 @@ enum BadMessageReason {
DSH_WRONG_STORAGE_PARTITION = 138,
BDH_DISALLOWED_ORIGIN = 139,
ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION = 140,
+ MDDH_INVALID_DEVICE_TYPE_REQUEST = 141,
+ MDDH_UNAUTHORIZED_ORIGIN = 142,
+ SWDH_ENABLE_NAVIGATION_PRELOAD_NO_HOST = 143,
+ SWDH_ENABLE_NAVIGATION_PRELOAD_INVALID_ORIGIN = 144,
+ SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID = 145,
+ RDH_TRANSFERRING_REQUEST_NOT_FOUND = 146, // Disabled - crbug.com/659613.
+ RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST = 147,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST = 148,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN = 149,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID = 150,
+ SWDH_SET_NAVIGATION_PRELOAD_HEADER_NO_HOST = 151,
+ SWDH_SET_NAVIGATION_PRELOAD_HEADER_INVALID_ORIGIN = 152,
+ SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_REGISTRATION_ID = 153,
+ SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_VALUE = 154,
+ MDDH_INVALID_SUBSCRIPTION_REQUEST = 155,
+ MDDH_INVALID_UNSUBSCRIPTION_REQUEST = 156,
+ AOAH_NONSENSE_DEVICE_ID = 157,
+ BDH_INVALID_OPTIONS = 158,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc b/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
index b2e9e108ae8..1daebec2426 100644
--- a/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
+++ b/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
@@ -20,7 +20,7 @@
#include "content/shell/browser/shell_content_browser_client.h"
#include "device/battery/battery_monitor.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
// These tests run against a dummy implementation of the BatteryMonitor service.
// That is, they verify that the service implementation is correctly exposed to
@@ -89,7 +89,7 @@ class FakeBatteryMonitor : public device::BatteryMonitor {
class TestContentBrowserClient : public ContentBrowserClient {
public:
void ExposeInterfacesToRenderer(
- shell::InterfaceRegistry* registry,
+ service_manager::InterfaceRegistry* registry,
RenderProcessHost* render_process_host) override {
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
diff --git a/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc b/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc
deleted file mode 100644
index 31cdc6676c3..00000000000
--- a/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "storage/browser/blob/blob_async_builder_host.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/shared_memory.h"
-#include "base/run_loop.h"
-#include "content/public/test/test_browser_thread_bundle.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"
-#include "storage/common/blob_storage/blob_storage_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace storage {
-namespace {
-const std::string kBlobUUID = "blobUUIDYAY";
-const std::string kContentType = "content_type";
-const std::string kContentDisposition = "content_disposition";
-const std::string kCompletedBlobUUID = "completedBlob";
-const std::string kCompletedBlobData = "completedBlobData";
-
-const size_t kTestBlobStorageIPCThresholdBytes = 5;
-const size_t kTestBlobStorageMaxSharedMemoryBytes = 20;
-const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
-
-void PopulateBytes(char* bytes, size_t length) {
- for (size_t i = 0; i < length; i++) {
- bytes[i] = static_cast<char>(i);
- }
-}
-
-void AddMemoryItem(size_t length, std::vector<DataElement>* out) {
- DataElement bytes;
- bytes.SetToBytesDescription(length);
- out->push_back(bytes);
-}
-
-void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) {
- DataElement bytes;
- bytes.SetToAllocatedBytes(length);
- PopulateBytes(bytes.mutable_bytes(), length);
- out->push_back(bytes);
-}
-
-void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) {
- DataElement bytes;
- bytes.SetToAllocatedBytes(length);
- PopulateBytes(bytes.mutable_bytes(), length);
- out->AppendData(bytes.bytes(), length);
-}
-
-void AddBlobItem(std::vector<DataElement>* out) {
- DataElement blob;
- blob.SetToBlob(kCompletedBlobUUID);
- out->push_back(blob);
-}
-} // namespace
-
-class BlobAsyncBuilderHostTest : public testing::Test {
- public:
- BlobAsyncBuilderHostTest()
- : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
- request_called_(false) {}
- ~BlobAsyncBuilderHostTest() override {}
-
- void SetUp() override {
- cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN;
- request_called_ = false;
- requests_.clear();
- memory_handles_.clear();
- host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
- kTestBlobStorageMaxSharedMemoryBytes,
- kTestBlobStorageMaxFileSizeBytes);
- BlobDataBuilder builder(kCompletedBlobUUID);
- builder.AppendData(kCompletedBlobData);
- completed_blob_handle_ = context_.AddFinishedBlob(builder);
- completed_blob_uuid_set_ = {kCompletedBlobUUID};
- }
-
- void RequestMemoryCallback(
- std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
- std::unique_ptr<std::vector<base::SharedMemoryHandle>>
- shared_memory_handles,
- std::unique_ptr<std::vector<base::File>> files) {
- requests_ = std::move(*requests);
- memory_handles_ = std::move(*shared_memory_handles);
- request_called_ = true;
- }
-
- BlobTransportResult BuildBlobAsync(
- const std::vector<DataElement>& descriptions,
- const std::set<std::string>& referenced_blob_uuids,
- size_t memory_available) {
- request_called_ = false;
- BlobTransportResult register_result =
- host_.RegisterBlobUUID(kBlobUUID, kContentType, kContentDisposition,
- referenced_blob_uuids, &context_);
- if (register_result != BlobTransportResult::DONE) {
- return register_result;
- }
- return host_.StartBuildingBlob(
- kBlobUUID, descriptions, memory_available, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this)));
- }
-
- void DecrementBlobRefCount(const std::string& uuid) {
- context_.DecrementBlobRefCount(uuid);
- }
-
- bool IsBeingBuiltInContext(const std::string& uuid) {
- return context_.IsBeingBuilt(uuid);
- }
-
- content::TestBrowserThreadBundle browser_thread_bundle_;
- BlobStorageContext context_;
- BlobAsyncBuilderHost host_;
- IPCBlobCreationCancelCode cancel_code_;
-
- bool request_called_;
- std::vector<storage::BlobItemBytesRequest> requests_;
- std::vector<base::SharedMemoryHandle> memory_handles_;
- std::set<std::string> completed_blob_uuid_set_;
-
- std::unique_ptr<BlobDataHandle> completed_blob_handle_;
-};
-
-// The 'shortcut' method is when the data is included in the initial IPCs and
-// the browser uses that instead of requesting the memory.
-TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
- std::vector<DataElement> descriptions;
-
- AddShortcutMemoryItem(10, &descriptions);
- AddBlobItem(&descriptions);
- AddShortcutMemoryItem(5000, &descriptions);
-
- BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kContentType);
- expected.set_content_disposition(kContentDisposition);
- AddShortcutMemoryItem(10, &expected);
- expected.AppendData(kCompletedBlobData);
- AddShortcutMemoryItem(5000, &expected);
-
- EXPECT_EQ(BlobTransportResult::DONE,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
-
- EXPECT_FALSE(request_called_);
- EXPECT_EQ(0u, host_.blob_building_count());
- std::unique_ptr<BlobDataHandle> handle =
- context_.GetBlobDataFromUUID(kBlobUUID);
- EXPECT_FALSE(handle->IsBeingBuilt());
- EXPECT_FALSE(handle->IsBroken());
- std::unique_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
- EXPECT_EQ(expected, *data);
- data.reset();
- handle.reset();
- base::RunLoop().RunUntilIdle();
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestShortcutNoRoom) {
- std::vector<DataElement> descriptions;
-
- AddShortcutMemoryItem(10, &descriptions);
- AddBlobItem(&descriptions);
- AddShortcutMemoryItem(5000, &descriptions);
-
- EXPECT_EQ(BlobTransportResult::CANCEL_MEMORY_FULL,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5000));
-
- EXPECT_FALSE(request_called_);
- EXPECT_EQ(0u, host_.blob_building_count());
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) {
- std::vector<DataElement> descriptions;
- const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
- AddMemoryItem(kSize, &descriptions);
-
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, std::set<std::string>(),
- kTestBlobStorageIPCThresholdBytes + 1));
-
- EXPECT_TRUE(request_called_);
- EXPECT_EQ(1u, host_.blob_building_count());
- ASSERT_EQ(1u, requests_.size());
- request_called_ = false;
-
- EXPECT_EQ(
- BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0),
- requests_.at(0));
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
- std::vector<DataElement> descriptions;
- const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1;
- const char kFirstBlockByte = 7;
- const char kSecondBlockByte = 19;
- AddMemoryItem(kSize, &descriptions);
-
- BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kContentType);
- expected.set_content_disposition(kContentDisposition);
- char data[kSize];
- memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
- expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
- expected.AppendData(&kSecondBlockByte, 1);
-
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, std::set<std::string>(),
- kTestBlobStorageMaxSharedMemoryBytes + 1));
-
- EXPECT_TRUE(request_called_);
- EXPECT_EQ(1u, host_.blob_building_count());
- ASSERT_EQ(1u, requests_.size());
- request_called_ = false;
-
- // We need to grab a duplicate handle so we can have two blocks open at the
- // same time.
- base::SharedMemoryHandle handle =
- base::SharedMemory::DuplicateHandle(memory_handles_.at(0));
- EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle));
- base::SharedMemory shared_memory(handle, false);
- EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes));
-
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
- 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0),
- requests_.at(0));
-
- memset(shared_memory.memory(), kFirstBlockByte,
- kTestBlobStorageMaxSharedMemoryBytes);
-
- BlobItemBytesResponse response(0);
- std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
-
- EXPECT_TRUE(request_called_);
- EXPECT_EQ(1u, host_.blob_building_count());
- ASSERT_EQ(1u, requests_.size());
- request_called_ = false;
-
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
- 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0),
- requests_.at(0));
-
- memset(shared_memory.memory(), kSecondBlockByte, 1);
-
- response.request_number = 1;
- responses[0] = response;
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_FALSE(request_called_);
- EXPECT_EQ(0u, host_.blob_building_count());
- std::unique_ptr<BlobDataHandle> blob_handle =
- context_.GetBlobDataFromUUID(kBlobUUID);
- EXPECT_FALSE(blob_handle->IsBeingBuilt());
- EXPECT_FALSE(blob_handle->IsBroken());
- std::unique_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
- EXPECT_EQ(expected, *blob_data);
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
- std::vector<DataElement> descriptions;
-
- AddMemoryItem(2, &descriptions);
- AddBlobItem(&descriptions);
- AddMemoryItem(2, &descriptions);
-
- BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kContentType);
- expected.set_content_disposition(kContentDisposition);
- AddShortcutMemoryItem(2, &expected);
- expected.AppendData(kCompletedBlobData);
- AddShortcutMemoryItem(2, &expected);
-
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
- &context_);
-
- // Check that we're broken, and then remove the blob.
- std::unique_ptr<BlobDataHandle> blob_handle =
- context_.GetBlobDataFromUUID(kBlobUUID);
- EXPECT_FALSE(blob_handle->IsBeingBuilt());
- EXPECT_TRUE(blob_handle->IsBroken());
- blob_handle.reset();
- DecrementBlobRefCount(kBlobUUID);
- base::RunLoop().RunUntilIdle();
- blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
- EXPECT_FALSE(blob_handle.get());
-
- // This should succeed because we've removed all references to the blob.
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
-
- EXPECT_TRUE(request_called_);
- EXPECT_EQ(1u, host_.blob_building_count());
- request_called_ = false;
-
- BlobItemBytesResponse response1(0);
- PopulateBytes(response1.allocate_mutable_data(2), 2);
- BlobItemBytesResponse response2(1);
- PopulateBytes(response2.allocate_mutable_data(2), 2);
- std::vector<BlobItemBytesResponse> responses = {response1, response2};
-
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_FALSE(request_called_);
- EXPECT_EQ(0u, host_.blob_building_count());
- blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
- EXPECT_FALSE(blob_handle->IsBeingBuilt());
- EXPECT_FALSE(blob_handle->IsBroken());
- std::unique_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
- EXPECT_EQ(expected, *blob_data);
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestBreakingAllBuilding) {
- const std::string& kBlob1 = "blob1";
- const std::string& kBlob2 = "blob2";
- const std::string& kBlob3 = "blob3";
-
- // Register blobs.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
-
- // Start building one of them.
- std::vector<DataElement> descriptions;
- AddMemoryItem(2, &descriptions);
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- host_.StartBuildingBlob(
- kBlob1, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_TRUE(request_called_);
-
- std::unique_ptr<BlobDataHandle> blob_handle1 =
- context_.GetBlobDataFromUUID(kBlob1);
- std::unique_ptr<BlobDataHandle> blob_handle2 =
- context_.GetBlobDataFromUUID(kBlob2);
- std::unique_ptr<BlobDataHandle> blob_handle3 =
- context_.GetBlobDataFromUUID(kBlob2);
- EXPECT_TRUE(blob_handle1->IsBeingBuilt() && blob_handle2->IsBeingBuilt() &&
- blob_handle3->IsBeingBuilt());
- EXPECT_FALSE(blob_handle1->IsBroken() || blob_handle2->IsBroken() ||
- blob_handle3->IsBroken());
-
- host_.CancelAll(&context_);
-
- EXPECT_FALSE(blob_handle1->IsBeingBuilt() || blob_handle2->IsBeingBuilt() ||
- blob_handle3->IsBeingBuilt());
- EXPECT_TRUE(blob_handle1->IsBroken() && blob_handle2->IsBroken() &&
- blob_handle3->IsBroken());
- blob_handle1.reset();
- blob_handle2.reset();
- blob_handle3.reset();
- base::RunLoop().RunUntilIdle();
-};
-
-TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) {
- std::vector<DataElement> descriptions;
-
- // Test reusing same blob uuid.
- AddMemoryItem(10, &descriptions);
- AddBlobItem(&descriptions);
- AddMemoryItem(5000, &descriptions);
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- EXPECT_FALSE(request_called_);
- host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
- &context_);
- base::RunLoop().RunUntilIdle();
- DecrementBlobRefCount(kBlobUUID);
- EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
-
- // Test we're an error if we get a bad uuid for responses.
- BlobItemBytesResponse response(0);
- std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
-
- // Test empty responses.
- responses.clear();
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
-
- // Test response problems below here.
- descriptions.clear();
- AddMemoryItem(2, &descriptions);
- AddBlobItem(&descriptions);
- AddMemoryItem(2, &descriptions);
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
-
- // Invalid request number.
- BlobItemBytesResponse response1(3);
- PopulateBytes(response1.allocate_mutable_data(2), 2);
- responses = {response1};
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
- DecrementBlobRefCount(kBlobUUID);
- base::RunLoop().RunUntilIdle();
-
- // Duplicate request number responses.
- EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
- BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- response1.request_number = 0;
- BlobItemBytesResponse response2(0);
- PopulateBytes(response2.allocate_mutable_data(2), 2);
- responses = {response1, response2};
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
- DecrementBlobRefCount(kBlobUUID);
- base::RunLoop().RunUntilIdle();
-};
-
-TEST_F(BlobAsyncBuilderHostTest, WaitOnReferencedBlob) {
- const std::string& kBlob1 = "blob1";
- const std::string& kBlob2 = "blob2";
- const std::string& kBlob3 = "blob3";
-
- // Register blobs.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
- {kBlob1, kBlob2}, &context_));
-
- // Finish the third one, with a reference to the first and second blob.
- std::vector<DataElement> descriptions;
- AddShortcutMemoryItem(2, &descriptions);
- DataElement element;
- element.SetToBlob(kBlob1);
- descriptions.push_back(element);
- element.SetToBlob(kBlob2);
- descriptions.push_back(element);
-
- // Finish the third, but we should still be 'building' it.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.StartBuildingBlob(
- kBlob3, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(request_called_);
- EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
- EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
-
- // Finish the first.
- descriptions.clear();
- AddShortcutMemoryItem(2, &descriptions);
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.StartBuildingBlob(
- kBlob1, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(request_called_);
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
-
- // Run the message loop so we propogate the construction complete callbacks.
- base::RunLoop().RunUntilIdle();
- // Verify we're not done.
- EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
- EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
-
- // Finish the second.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.StartBuildingBlob(
- kBlob2, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(request_called_);
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
-
- // Run the message loop so we propogate the construction complete callbacks.
- base::RunLoop().RunUntilIdle();
- // Finally, we should be finished with third blob.
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
-};
-
-TEST_F(BlobAsyncBuilderHostTest, IncorrectBlobDependencies) {
- const std::string& kGoodBlob = "goodBlob";
- const std::string& kBlob1 = "blob1";
- const std::string& kBlob2 = "blob2";
- const std::string& kBlob3 = "blob3";
-
- // Register blobs. Blob 1 has a reference to itself, Blob 2 has a reference
- // but doesn't use it, and blob 3 doesn't list it's reference.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kGoodBlob, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
- {kBlob1}, &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
- {kGoodBlob}, &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
-
- // The first blob shouldn't be building anymore.
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
-
- // Try to finish the second one, without a reference to the first.
- std::vector<DataElement> descriptions;
- AddShortcutMemoryItem(2, &descriptions);
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.StartBuildingBlob(
- kBlob2, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
-
- // Try to finish the third one with the reference we didn't declare earlier.
- descriptions.clear();
- AddShortcutMemoryItem(2, &descriptions);
- DataElement element;
- element.SetToBlob(kGoodBlob);
- descriptions.push_back(element);
- EXPECT_EQ(BlobTransportResult::BAD_IPC,
- host_.StartBuildingBlob(
- kBlob3, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
-};
-
-TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBreaks) {
- const std::string& kBlob1 = "blob1";
- const std::string& kBlob2 = "blob2";
-
- // Register blobs.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
- {kBlob1}, &context_));
-
- // Finish the second one, with a reference to the first.
- std::vector<DataElement> descriptions;
- AddShortcutMemoryItem(2, &descriptions);
- DataElement element;
- element.SetToBlob(kBlob1);
- descriptions.push_back(element);
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.StartBuildingBlob(
- kBlob2, descriptions, 2, &context_,
- base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this))));
- EXPECT_FALSE(request_called_);
- EXPECT_TRUE(host_.IsBeingBuilt(kBlob2));
- EXPECT_TRUE(IsBeingBuiltInContext(kBlob2));
-
- // Break the first.
- descriptions.clear();
- host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
- &context_);
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1)->IsBroken());
-
- // Run the message loop so we propogate the construction complete callbacks.
- base::RunLoop().RunUntilIdle();
- // We should be finished with third blob, and it should be broken.
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
-};
-
-TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBroken) {
- const std::string& kBlob1 = "blob1";
- const std::string& kBlob2 = "blob2";
-
- // Register blobs.
- EXPECT_EQ(BlobTransportResult::DONE,
- host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
- std::set<std::string>(), &context_));
- host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
- &context_);
- EXPECT_EQ(BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN,
- host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
- {kBlob1}, &context_));
- EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
- EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
- EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
-};
-
-} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_data_builder_unittest.cc b/chromium/content/browser/blob_storage/blob_data_builder_unittest.cc
new file mode 100644
index 00000000000..f1fc6a9a6a6
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_data_builder_unittest.cc
@@ -0,0 +1,31 @@
+// 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 "storage/browser/blob/blob_data_builder.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "storage/common/data_element.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+TEST(BlobDataBuilderTest, TestFutureFiles) {
+ const std::string kId = "id";
+
+ DataElement element;
+ element.SetToFilePath(BlobDataBuilder::GetFutureFileItemPath(0));
+ EXPECT_TRUE(BlobDataBuilder::IsFutureFileItem(element));
+ EXPECT_EQ(0ull, BlobDataBuilder::GetFutureFileID(element));
+
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureFile(0, 10, 0);
+ EXPECT_TRUE(
+ BlobDataBuilder::IsFutureFileItem(builder.items_[0]->data_element()));
+ EXPECT_EQ(0ull, BlobDataBuilder::GetFutureFileID(
+ builder.items_[0]->data_element()));
+}
+
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host.cc b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
index 2269cc645ef..bea813ddc5c 100644
--- a/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
@@ -14,8 +14,9 @@
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/common/fileapi/webblob_messages.h"
#include "ipc/ipc_platform_file.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_entry.h"
#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/blob_transport_result.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
@@ -25,13 +26,17 @@
using storage::BlobStorageContext;
using storage::BlobStorageRegistry;
-using storage::BlobTransportResult;
+using storage::BlobStatus;
using storage::DataElement;
-using storage::IPCBlobCreationCancelCode;
using storage::FileSystemURL;
namespace content {
namespace {
+using storage::BlobStorageContext;
+using storage::BlobStorageRegistry;
+using storage::BlobStatus;
+using storage::DataElement;
+using storage::FileSystemURL;
// These are used for UMA stats, don't change.
enum RefcountOperation {
@@ -42,6 +47,16 @@ enum RefcountOperation {
} // namespace
+BlobDispatcherHost::HostedBlobState::HostedBlobState(
+ std::unique_ptr<storage::BlobDataHandle> handle)
+ : handle(std::move(handle)) {}
+BlobDispatcherHost::HostedBlobState::~HostedBlobState() {}
+
+BlobDispatcherHost::HostedBlobState::HostedBlobState(HostedBlobState&&) =
+ default;
+BlobDispatcherHost::HostedBlobState& BlobDispatcherHost::HostedBlobState::
+operator=(BlobDispatcherHost::HostedBlobState&&) = default;
+
BlobDispatcherHost::BlobDispatcherHost(
int process_id,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
@@ -63,11 +78,11 @@ void BlobDispatcherHost::OnChannelClosing() {
bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
+ // Note: The only time a renderer sends a blob status message is to cancel.
IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlob, OnRegisterBlob)
IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_SendBlobStatus, OnCancelBuildingBlob)
IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount)
IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount)
IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL)
@@ -77,75 +92,20 @@ bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void BlobDispatcherHost::OnRegisterBlobUUID(
+void BlobDispatcherHost::OnRegisterBlob(
const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition,
- const std::set<std::string>& referenced_blob_uuids) {
+ const std::vector<storage::DataElement>& descriptions) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BlobStorageContext* context = this->context();
if (uuid.empty() || context->registry().HasEntry(uuid) ||
- async_builder_.IsBeingBuilt(uuid)) {
+ transport_host_.IsBeingBuilt(uuid)) {
bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED);
return;
}
- blobs_inuse_map_[uuid] = 1;
- BlobTransportResult result = async_builder_.RegisterBlobUUID(
- uuid, content_type, content_disposition, referenced_blob_uuids, context);
- switch (result) {
- case BlobTransportResult::BAD_IPC:
- blobs_inuse_map_.erase(uuid);
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_CONSTRUCTION_FAILED);
- break;
- case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
- // The async builder builds the blob as broken, and we just need to send
- // the cancel message back to the renderer.
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
- break;
- case BlobTransportResult::DONE:
- break;
- case BlobTransportResult::CANCEL_MEMORY_FULL:
- case BlobTransportResult::CANCEL_FILE_ERROR:
- case BlobTransportResult::CANCEL_UNKNOWN:
- case BlobTransportResult::PENDING_RESPONSES:
- NOTREACHED();
- break;
- }
-}
-void BlobDispatcherHost::OnStartBuildingBlob(
- const std::string& uuid,
- const std::vector<storage::DataElement>& descriptions) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
- return;
- }
- BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
- // We ignore messages for blobs that don't exist to handle the case where
- // the renderer de-refs a blob that we're still constructing, and there are
- // no references to that blob. We ignore broken as well, in the case where
- // we decided to break a blob after RegisterBlobUUID is called.
- // Second, if the last dereference of the blob happened on a different host,
- // then we still haven't gotten rid of the 'building' state in the original
- // host. So we call cancel, and send the message just in case that happens.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
- }
- return;
- }
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
- return;
- }
+ DCHECK(!base::ContainsKey(blobs_inuse_map_, uuid));
ChildProcessSecurityPolicyImpl* security_policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -159,20 +119,24 @@ void BlobDispatcherHost::OnStartBuildingBlob(
if (!FileSystemURLIsValid(file_system_context_.get(), filesystem_url) ||
!security_policy->CanReadFileSystemFile(process_id_,
filesystem_url)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
+ HostedBlobState hosted_state(
+ context->AddBrokenBlob(uuid, content_type, content_disposition,
+ BlobStatus::ERR_FILE_WRITE_FAILED));
+ blobs_inuse_map_.insert(
+ std::make_pair(uuid, std::move(hosted_state)));
+ SendFinalBlobStatus(uuid, BlobStatus::ERR_FILE_WRITE_FAILED);
return;
}
break;
}
case storage::DataElement::TYPE_FILE: {
if (!security_policy->CanReadFile(process_id_, item.path())) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
+ HostedBlobState hosted_state(
+ context->AddBrokenBlob(uuid, content_type, content_disposition,
+ BlobStatus::ERR_FILE_WRITE_FAILED));
+ blobs_inuse_map_.insert(
+ std::make_pair(uuid, std::move(hosted_state)));
+ SendFinalBlobStatus(uuid, BlobStatus::ERR_FILE_WRITE_FAILED);
return;
}
break;
@@ -193,12 +157,13 @@ void BlobDispatcherHost::OnStartBuildingBlob(
}
}
- // |this| owns async_builder_ so using base::Unretained(this) is safe.
- BlobTransportResult result = async_builder_.StartBuildingBlob(
- uuid, descriptions, context->memory_available(), context,
+ HostedBlobState hosted_state(transport_host_.StartBuildingBlob(
+ uuid, content_type, content_disposition, descriptions, context,
base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
- uuid));
- SendIPCResponse(uuid, result);
+ uuid),
+ base::Bind(&BlobDispatcherHost::SendFinalBlobStatus,
+ base::Unretained(this), uuid)));
+ blobs_inuse_map_.insert(std::make_pair(uuid, std::move(hosted_state)));
}
void BlobDispatcherHost::OnMemoryItemResponse(
@@ -206,71 +171,65 @@ void BlobDispatcherHost::OnMemoryItemResponse(
const std::vector<storage::BlobItemBytesResponse>& responses) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ const storage::BlobEntry* entry = context->registry().GetEntry(uuid);
+ if (!entry || BlobStatusIsError(entry->status())) {
// We ignore messages for blobs that don't exist to handle the case where
// the renderer de-refs a blob that we're still constructing, and there are
// no references to that blob. We ignore broken as well, in the case where
// we decided to break a blob after sending the memory request.
- // Note: if a blob is broken, then it can't be in the async_builder.
+ // Note: if a blob is broken, then it can't be in the transport_host.
// Second, if the last dereference of the blob happened on a different host,
// then we still haven't gotten rid of the 'building' state in the original
// host. So we call cancel, and send the message just in case that happens.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ if (transport_host_.IsBeingBuilt(uuid)) {
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
return;
}
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ if (!transport_host_.IsBeingBuilt(uuid)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
- BlobTransportResult result =
- async_builder_.OnMemoryResponses(uuid, responses, context);
- SendIPCResponse(uuid, result);
+ transport_host_.OnMemoryResponses(uuid, responses, context);
}
-void BlobDispatcherHost::OnCancelBuildingBlob(
- const std::string& uuid,
- const storage::IPCBlobCreationCancelCode code) {
+void BlobDispatcherHost::OnCancelBuildingBlob(const std::string& uuid,
+ const storage::BlobStatus code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ const storage::BlobEntry* entry = context->registry().GetEntry(uuid);
+ if (!entry || BlobStatusIsError(entry->status())) {
// We ignore messages for blobs that don't exist to handle the case where
// the renderer de-refs a blob that we're still constructing, and there are
// no references to that blob. We ignore broken as well, in the case where
// we decided to break a blob and the renderer also decided to cancel.
- // Note: if a blob is broken, then it can't be in the async_builder.
+ // Note: if a blob is broken, then it can't be in the transport_host.
// Second, if the last dereference of the blob happened on a different host,
// then we still haven't gotten rid of the 'building' state in the original
// host. So we call cancel just in case this happens.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
+ if (transport_host_.IsBeingBuilt(uuid)) {
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
return;
}
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ if (!transport_host_.IsBeingBuilt(uuid) ||
+ !storage::BlobStatusIsError(code)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. "
<< " Reason: " << static_cast<int>(code) << ".";
- async_builder_.CancelBuildingBlob(uuid, code, context);
+ transport_host_.CancelBuildingBlob(uuid, code, context);
}
void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
@@ -286,8 +245,13 @@ void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
BDH_TRACING_ENUM_LAST);
return;
}
- context->IncrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] += 1;
+ auto state_it = blobs_inuse_map_.find(uuid);
+ if (state_it != blobs_inuse_map_.end()) {
+ state_it->second.refcount += 1;
+ return;
+ }
+ blobs_inuse_map_.insert(std::make_pair(
+ uuid, HostedBlobState(context->GetBlobDataFromUUID(uuid))));
}
void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
@@ -297,26 +261,23 @@ void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
this, bad_message::BDH_INVALID_REFCOUNT_OPERATION);
return;
}
- if (!IsInUseInHost(uuid)) {
+ auto state_it = blobs_inuse_map_.find(uuid);
+ if (state_it == blobs_inuse_map_.end()) {
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_DECREMENT,
BDH_TRACING_ENUM_LAST);
return;
}
- BlobStorageContext* context = this->context();
- context->DecrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] -= 1;
- if (blobs_inuse_map_[uuid] == 0) {
- blobs_inuse_map_.erase(uuid);
- // If the blob has been deleted in the context and we're still building it,
- // this means we have no references waiting to read it. Clear the building
- // state and send a cancel message to the renderer.
- if (async_builder_.IsBeingBuilt(uuid) &&
+ state_it->second.refcount -= 1;
+ if (state_it->second.refcount == 0) {
+ blobs_inuse_map_.erase(state_it);
+
+ // If we're being built still and we don't have any other references, cancel
+ // construction.
+ BlobStorageContext* context = this->context();
+ if (transport_host_.IsBeingBuilt(uuid) &&
!context->registry().HasEntry(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
}
}
@@ -372,55 +333,33 @@ storage::BlobStorageContext* BlobDispatcherHost::context() {
void BlobDispatcherHost::SendMemoryRequest(
const std::string& uuid,
- std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
- std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
- std::unique_ptr<std::vector<base::File>> files) {
+ std::vector<storage::BlobItemBytesRequest> requests,
+ std::vector<base::SharedMemoryHandle> memory_handles,
+ std::vector<base::File> files) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<IPC::PlatformFileForTransit> file_handles;
- // TODO(dmurph): Support file-backed blob transportation.
- DCHECK(files->empty());
- Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles,
+ for (base::File& file : files) {
+ file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file)));
+ }
+ Send(new BlobStorageMsg_RequestMemoryItem(uuid, requests, memory_handles,
file_handles));
}
-void BlobDispatcherHost::SendIPCResponse(const std::string& uuid,
- storage::BlobTransportResult result) {
- switch (result) {
- case BlobTransportResult::BAD_IPC:
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_CONSTRUCTION_FAILED);
- return;
- case BlobTransportResult::CANCEL_MEMORY_FULL:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY));
- return;
- case BlobTransportResult::CANCEL_FILE_ERROR:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
- return;
- case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
- return;
- case BlobTransportResult::CANCEL_UNKNOWN:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::UNKNOWN));
- return;
- case BlobTransportResult::PENDING_RESPONSES:
- return;
- case BlobTransportResult::DONE:
- Send(new BlobStorageMsg_DoneBuildingBlob(uuid));
- return;
+void BlobDispatcherHost::SendFinalBlobStatus(const std::string& uuid,
+ BlobStatus status) {
+ DCHECK(!BlobStatusIsPending(status));
+ if (storage::BlobStatusIsBadIPC(status)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
}
- NOTREACHED();
+ Send(new BlobStorageMsg_SendBlobStatus(uuid, status));
}
bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) {
- return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
+ return base::ContainsKey(blobs_inuse_map_, uuid);
}
bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) {
- return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
+ return base::ContainsKey(public_blob_urls_, blob_url);
}
void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
@@ -428,11 +367,9 @@ void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
for (const auto& url : public_blob_urls_) {
context->RevokePublicBlobURL(url);
}
- for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
- for (int i = 0; i < uuid_refnum_pair.second; ++i)
- context->DecrementBlobRefCount(uuid_refnum_pair.first);
- }
- async_builder_.CancelAll(context);
+ // Keep the blobs alive for the BlobTransportHost call.
+ transport_host_.CancelAll(context);
+ blobs_inuse_map_.clear();
}
} // namespace content
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host.h b/chromium/content/browser/blob_storage/blob_dispatcher_host.h
index f9d1a98881e..e1bfbe50411 100644
--- a/chromium/content/browser/blob_storage/blob_dispatcher_host.h
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_BLOB_STORAGE_BLOB_DISPATCHER_HOST_H_
#define CONTENT_BROWSER_BLOB_STORAGE_BLOB_DISPATCHER_HOST_H_
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -16,19 +17,14 @@
#include "base/memory/shared_memory_handle.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
-#include "storage/browser/blob/blob_async_builder_host.h"
-#include "storage/browser/blob/blob_transport_result.h"
+#include "storage/browser/blob/blob_transport_host.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
class GURL;
-namespace IPC {
-class Sender;
-}
-
namespace storage {
class DataElement;
-class BlobDataBuilder;
+class BlobDataHandle;
struct BlobItemBytesRequest;
struct BlobItemBytesResponse;
class BlobStorageContext;
@@ -58,14 +54,6 @@ class CONTENT_EXPORT BlobDispatcherHost : public BrowserMessageFilter {
protected:
~BlobDispatcherHost() override;
- // For testing use only.
- void SetMemoryConstantsForTesting(size_t max_ipc_memory_size,
- size_t max_shared_memory_size,
- uint64_t max_file_size) {
- async_builder_.SetMemoryConstantsForTesting(
- max_ipc_memory_size, max_shared_memory_size, max_file_size);
- }
-
private:
friend class base::RefCountedThreadSafe<BlobDispatcherHost>;
friend class BlobDispatcherHostTest;
@@ -98,20 +86,15 @@ class CONTENT_EXPORT BlobDispatcherHost : public BrowserMessageFilter {
FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
BuildingReferenceChainWithSourceDeath);
- typedef std::map<std::string, int> BlobReferenceMap;
-
- void OnRegisterBlobUUID(const std::string& uuid,
- const std::string& content_type,
- const std::string& content_disposition,
- const std::set<std::string>& referenced_blob_uuids);
- void OnStartBuildingBlob(
- const std::string& uuid,
- const std::vector<storage::DataElement>& descriptions);
+ void OnRegisterBlob(const std::string& uuid,
+ const std::string& content_type,
+ const std::string& content_disposition,
+ const std::vector<storage::DataElement>& descriptions);
void OnMemoryItemResponse(
const std::string& uuid,
const std::vector<storage::BlobItemBytesResponse>& response);
void OnCancelBuildingBlob(const std::string& uuid,
- const storage::IPCBlobCreationCancelCode code);
+ const storage::BlobStatus code);
void OnIncrementBlobRefCount(const std::string& uuid);
void OnDecrementBlobRefCount(const std::string& uuid);
@@ -120,15 +103,14 @@ class CONTENT_EXPORT BlobDispatcherHost : public BrowserMessageFilter {
storage::BlobStorageContext* context();
- void SendMemoryRequest(
- const std::string& uuid,
- std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
- std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
- std::unique_ptr<std::vector<base::File>> files);
+ void SendMemoryRequest(const std::string& uuid,
+ std::vector<storage::BlobItemBytesRequest> requests,
+ std::vector<base::SharedMemoryHandle> memory_handles,
+ std::vector<base::File> files);
- // Send the appropriate IPC response to the renderer for the given result.
- void SendIPCResponse(const std::string& uuid,
- storage::BlobTransportResult result);
+ // The status should never be a pending status (see BlobStatusIsPending), and
+ // we ignore calls for |uuid|s that aren't in use in this host.
+ void SendFinalBlobStatus(const std::string& uuid, storage::BlobStatus status);
bool IsInUseInHost(const std::string& uuid);
bool IsUrlRegisteredInHost(const GURL& blob_url);
@@ -136,18 +118,29 @@ class CONTENT_EXPORT BlobDispatcherHost : public BrowserMessageFilter {
// Unregisters all blobs and urls that were registered in this host.
void ClearHostFromBlobStorageContext();
+ struct HostedBlobState {
+ explicit HostedBlobState(std::unique_ptr<storage::BlobDataHandle> handle);
+ ~HostedBlobState();
+ HostedBlobState(HostedBlobState&&);
+ HostedBlobState& operator=(HostedBlobState&&);
+ DISALLOW_COPY_AND_ASSIGN(HostedBlobState);
+
+ int refcount = 1;
+ std::unique_ptr<storage::BlobDataHandle> handle;
+ };
+
const int process_id_;
scoped_refptr<storage::FileSystemContext> file_system_context_;
// Collection of blob ids and a count of how many usages
// of that id are attributable to this consumer.
- BlobReferenceMap blobs_inuse_map_;
+ std::unordered_map<std::string, HostedBlobState> blobs_inuse_map_;
// The set of public blob urls coined by this consumer.
std::set<GURL> public_blob_urls_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
- storage::BlobAsyncBuilderHost async_builder_;
+ storage::BlobTransportHost transport_host_;
DISALLOW_COPY_AND_ASSIGN(BlobDispatcherHost);
};
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc b/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
index e51df6baa50..aca858fa1a4 100644
--- a/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/common/fileapi/webblob_messages.h"
#include "content/public/common/content_switches.h"
@@ -33,12 +34,10 @@ using storage::BlobDataBuilder;
using storage::BlobDataHandle;
using storage::BlobItemBytesRequest;
using storage::BlobItemBytesResponse;
+using storage::BlobStatus;
using storage::BlobStorageContext;
-using storage::BlobTransportResult;
using storage::DataElement;
-using storage::IPCBlobCreationCancelCode;
-using RequestMemoryCallback =
- storage::BlobAsyncBuilderHost::RequestMemoryCallback;
+using RequestMemoryCallback = storage::BlobTransportHost::RequestMemoryCallback;
namespace content {
namespace {
@@ -50,14 +49,16 @@ const size_t kDataSize = 6;
const size_t kTestBlobStorageIPCThresholdBytes = 20;
const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
+const size_t kTestBlobStorageMaxBlobMemorySize = 400;
+const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
+const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
-void ConstructionCompletePopulator(bool* succeeded_pointer,
- IPCBlobCreationCancelCode* reason_pointer,
- bool succeeded,
- IPCBlobCreationCancelCode reason) {
- *succeeded_pointer = succeeded;
+void ConstructionCompletePopulator(bool* success_pointer,
+ BlobStatus* reason_pointer,
+ BlobStatus reason) {
*reason_pointer = reason;
+ *success_pointer = reason == BlobStatus::DONE;
}
// TODO(dmurph): Create file test that verifies security policy.
@@ -69,11 +70,7 @@ class TestableBlobDispatcherHost : public BlobDispatcherHost {
: BlobDispatcherHost(0 /* process_id */,
make_scoped_refptr(blob_storage_context),
make_scoped_refptr(file_system_context)),
- sink_(sink) {
- this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
- kTestBlobStorageMaxSharedMemoryBytes,
- kTestBlobStorageMaxFileSizeBytes);
- }
+ sink_(sink) {}
bool Send(IPC::Message* message) override { return sink_->Send(message); }
@@ -112,7 +109,16 @@ class BlobDispatcherHostTest : public testing::Test {
// We run the run loop to initialize the chrome blob storage context.
base::RunLoop().RunUntilIdle();
context_ = chrome_blob_storage_context_->context();
- DCHECK(context_);
+ ASSERT_TRUE(context_);
+
+ storage::BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ context_->mutable_memory_controller()->set_limits_for_testing(limits);
}
void ExpectBlobNotExist(const std::string& id) {
@@ -124,14 +130,11 @@ class BlobDispatcherHostTest : public testing::Test {
void AsyncShortcutBlobTransfer(const std::string& id) {
sink_.ClearMessages();
ExpectBlobNotExist(id);
- host_->OnRegisterBlobUUID(id, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
DataElement element;
element.SetToBytes(kData, kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(id, elements);
+ host_->OnRegisterBlob(id, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
ExpectDone(id);
sink_.ClearMessages();
@@ -140,14 +143,11 @@ class BlobDispatcherHostTest : public testing::Test {
void AsyncBlobTransfer(const std::string& id) {
sink_.ClearMessages();
ExpectBlobNotExist(id);
- host_->OnRegisterBlobUUID(id, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(id, elements);
+ host_->OnRegisterBlob(id, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
// Expect our request.
@@ -187,9 +187,7 @@ class BlobDispatcherHostTest : public testing::Test {
const std::string& expected_uuid,
const std::vector<BlobItemBytesRequest>& expected_requests) {
EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
- EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
+ sink_.GetFirstMessageMatching(BlobStorageMsg_SendBlobStatus::ID));
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
ASSERT_TRUE(message);
@@ -211,9 +209,7 @@ class BlobDispatcherHostTest : public testing::Test {
const std::vector<BlobItemBytesRequest>& expected_requests,
std::vector<base::SharedMemoryHandle>* shared_memory_handles) {
EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
- EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
+ sink_.GetFirstMessageMatching(BlobStorageMsg_SendBlobStatus::ID));
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
ASSERT_TRUE(message);
@@ -231,17 +227,14 @@ class BlobDispatcherHostTest : public testing::Test {
*shared_memory_handles = std::move(std::get<2>(args));
}
- void ExpectCancel(const std::string& expected_uuid,
- IPCBlobCreationCancelCode code) {
+ void ExpectCancel(const std::string& expected_uuid, BlobStatus code) {
EXPECT_FALSE(
sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID));
- EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
const IPC::Message* message =
- sink_.GetUniqueMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID);
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_SendBlobStatus::ID);
ASSERT_TRUE(message);
- std::tuple<std::string, IPCBlobCreationCancelCode> args;
- BlobStorageMsg_CancelBuildingBlob::Read(message, &args);
+ std::tuple<std::string, BlobStatus> args;
+ BlobStorageMsg_SendBlobStatus::Read(message, &args);
EXPECT_EQ(expected_uuid, std::get<0>(args));
EXPECT_EQ(code, std::get<1>(args));
}
@@ -249,17 +242,21 @@ class BlobDispatcherHostTest : public testing::Test {
void ExpectDone(const std::string& expected_uuid) {
EXPECT_FALSE(
sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID));
- EXPECT_FALSE(
- sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
const IPC::Message* message =
- sink_.GetUniqueMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID);
- std::tuple<std::string> args;
- BlobStorageMsg_DoneBuildingBlob::Read(message, &args);
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_SendBlobStatus::ID);
+ ASSERT_TRUE(message);
+ std::tuple<std::string, BlobStatus> args;
+ BlobStorageMsg_SendBlobStatus::Read(message, &args);
EXPECT_EQ(expected_uuid, std::get<0>(args));
+ EXPECT_EQ(BlobStatus::DONE, std::get<1>(args));
}
bool IsBeingBuiltInHost(const std::string& uuid) {
- return host_->async_builder_.IsBeingBuilt(uuid);
+ return host_->transport_host_.IsBeingBuilt(uuid);
+ }
+
+ bool IsBeingBuiltInContext(const std::string& uuid) {
+ return BlobStatusIsPending(context_->GetBlobStatus(uuid));
}
IPC::TestSink sink_;
@@ -272,13 +269,12 @@ class BlobDispatcherHostTest : public testing::Test {
};
TEST_F(BlobDispatcherHostTest, EmptyUUIDs) {
- host_->OnRegisterBlobUUID("", "", "", std::set<std::string>());
- ExpectAndResetBadMessage();
- host_->OnStartBuildingBlob("", std::vector<DataElement>());
+ host_->OnRegisterBlob("", "", "", std::vector<DataElement>());
ExpectAndResetBadMessage();
host_->OnMemoryItemResponse("", std::vector<BlobItemBytesResponse>());
ExpectAndResetBadMessage();
- host_->OnCancelBuildingBlob("", IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob("",
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
ExpectAndResetBadMessage();
}
@@ -311,23 +307,16 @@ TEST_F(BlobDispatcherHostTest, RegularTransfer) {
TEST_F(BlobDispatcherHostTest, MultipleTransfers) {
const std::string kId = "uuid";
const int kNumIters = 10;
- for (int i = 0; i < kNumIters; i++) {
- std::string id = kId;
- id += ('0' + i);
- ExpectBlobNotExist(id);
- host_->OnRegisterBlobUUID(id, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
- }
sink_.ClearMessages();
for (int i = 0; i < kNumIters; i++) {
std::string id = kId;
id += ('0' + i);
+ ExpectBlobNotExist(id);
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(id, elements);
+ host_->OnRegisterBlob(id, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
// Expect our request.
std::vector<BlobItemBytesRequest> expected_requests = {
@@ -354,25 +343,23 @@ TEST_F(BlobDispatcherHostTest, SharedMemoryTransfer) {
std::vector<base::SharedMemoryHandle> shared_memory_handles;
ExpectBlobNotExist(kId);
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ DataElement element;
+ element.SetToBytesDescription(kLargeSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
// Grab the handle.
std::unique_ptr<BlobDataHandle> blob_data_handle =
context_->GetBlobDataFromUUID(kId);
bool built = false;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
blob_data_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
EXPECT_FALSE(built);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
- DataElement element;
- element.SetToBytesDescription(kLargeSize);
- std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
// Expect our first request.
std::vector<BlobItemBytesRequest> expected_requests = {
@@ -447,24 +434,23 @@ TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) {
const std::string kId("id");
// We ignore blobs that are unknown, as it could have been cancelled earlier
// and the renderer didn't know about it yet.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId,
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
// Start building blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
// It should have requested memory here.
EXPECT_FALSE(host_->shutdown_for_bad_message_);
sink_.ClearMessages();
// Cancel in middle of construction.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
EXPECT_TRUE(context_->registry().HasEntry(kId));
EXPECT_TRUE(host_->IsInUseInHost(kId));
EXPECT_FALSE(IsBeingBuiltInHost(kId));
@@ -492,7 +478,7 @@ TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) {
ExpectHandleEqualsData(handle.get(), expecteds);
// Verify we can't cancel after the fact.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
ExpectAndResetBadMessage();
}
@@ -524,9 +510,11 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) {
const std::string kId("id");
// Start building blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
// Grab the handle.
std::unique_ptr<BlobDataHandle> blob_data_handle =
@@ -534,15 +522,10 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) {
EXPECT_TRUE(blob_data_handle);
EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
bool built = false;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
blob_data_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
- // Continue building.
- DataElement element;
- element.SetToBytesDescription(kDataSize);
- std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
sink_.ClearMessages();
// Send data.
@@ -557,41 +540,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) {
EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code);
}
-TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) {
+TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) {
const std::string kId("id");
// Start building blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
-
- // Grab the handle.
- std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_->GetBlobDataFromUUID(kId);
- EXPECT_TRUE(blob_data_handle);
- EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
- bool built = false;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
- blob_data_handle->RunOnConstructionComplete(
- base::Bind(&ConstructionCompletePopulator, &built, &error_code));
-
- // Continue building.
DataElement element;
- element.SetToBytes(kData, kDataSize);
+ element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
- ExpectDone(kId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code);
-}
-
-TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) {
- const std::string kId("id");
-
- // Start building blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
// Grab the handle.
std::unique_ptr<BlobDataHandle> blob_data_handle =
@@ -599,25 +556,25 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) {
EXPECT_TRUE(blob_data_handle);
EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
bool built = true;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
blob_data_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
// Cancel in middle of construction.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(context_->registry().HasEntry(kId));
EXPECT_TRUE(host_->IsInUseInHost(kId));
EXPECT_FALSE(IsBeingBuiltInHost(kId));
EXPECT_TRUE(blob_data_handle->IsBroken());
EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
- error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code);
+ error_code = BlobStatus::ERR_OUT_OF_MEMORY;
built = true;
blob_data_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
+ EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code);
// Remove it.
blob_data_handle.reset();
@@ -627,59 +584,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) {
ExpectBlobNotExist(kId);
}
-TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) {
- const std::string kId("id");
- // Decrement the refcount while building (renderer blob gc'd before
- // construction was completed).
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_TRUE(context_->registry().HasEntry(kId));
- host_->OnDecrementBlobRefCount(kId);
- EXPECT_FALSE(context_->registry().HasEntry(kId));
- EXPECT_FALSE(IsBeingBuiltInHost(kId));
- ExpectCancel(kId,
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
- sink_.ClearMessages();
-
- // Do the same, but this time grab a handle before we decrement.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_->GetBlobDataFromUUID(kId);
- host_->OnDecrementBlobRefCount(kId);
- EXPECT_TRUE(context_->registry().HasEntry(kId));
- EXPECT_TRUE(IsBeingBuiltInHost(kId));
-
- // Finish up the blob, and verify we got the done message.
- DataElement element;
- element.SetToBytes(kData, kDataSize);
- std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
- ExpectDone(kId);
- sink_.ClearMessages();
- // Get rid of the handle, and verify it's gone.
- blob_data_handle.reset();
- base::RunLoop().RunUntilIdle();
- // Check that it's no longer around.
- EXPECT_FALSE(context_->registry().HasEntry(kId));
- EXPECT_FALSE(IsBeingBuiltInHost(kId));
-}
-
TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) {
const std::string kId("id");
// Decrement the refcount while building, after we call OnStartBuildlingBlob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
std::vector<BlobItemBytesRequest> expected_requests = {
@@ -690,16 +603,12 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) {
host_->OnDecrementBlobRefCount(kId);
EXPECT_FALSE(context_->registry().HasEntry(kId));
EXPECT_FALSE(IsBeingBuiltInHost(kId));
- ExpectCancel(kId,
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING);
sink_.ClearMessages();
// Do the same, but this time grab a handle to keep it alive.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
ExpectRequest(kId, expected_requests);
sink_.ClearMessages();
@@ -710,6 +619,7 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) {
host_->OnDecrementBlobRefCount(kId);
EXPECT_TRUE(context_->registry().HasEntry(kId));
EXPECT_TRUE(IsBeingBuiltInHost(kId));
+ EXPECT_EQ(0u, sink_.message_count());
// We finish the blob, and verify that we send 'Done' back to the renderer.
BlobItemBytesResponse response(0);
@@ -734,25 +644,21 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) {
const std::string kId("id");
// Decrement the refcount while building, after we call
// OnStartBuildlingBlob, except we have another handle.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
std::unique_ptr<BlobDataHandle> blob_data_handle =
context_->GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
bool built = true;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
blob_data_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
- DataElement element;
- element.SetToBytesDescription(kDataSize);
- std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
-
// Check that we got the expected request.
std::vector<BlobItemBytesRequest> expected_requests = {
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
@@ -767,14 +673,14 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) {
EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
EXPECT_TRUE(IsBeingBuiltInHost(kId));
// Cancel to clean up.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
// Run loop to propagate the handle decrement in the host.
base::RunLoop().RunUntilIdle();
// We still have the entry because of our earlier handle.
EXPECT_TRUE(context_->registry().HasEntry(kId));
EXPECT_FALSE(IsBeingBuiltInHost(kId));
EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
+ EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code);
sink_.ClearMessages();
// Should disappear after dropping the handle.
@@ -784,52 +690,15 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) {
EXPECT_FALSE(context_->registry().HasEntry(kId));
}
-TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) {
- const std::string kId("id");
-
- // Delete host with a handle to the blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
-
- std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_->GetBlobDataFromUUID(kId);
- EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
- bool built = true;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
- blob_data_handle->RunOnConstructionComplete(
- base::Bind(&ConstructionCompletePopulator, &built, &error_code));
- // Get rid of host, which was doing the constructing.
- host_ = nullptr;
- EXPECT_FALSE(blob_data_handle->IsBeingBuilt());
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code);
-
- // Should still be there due to the handle.
- std::unique_ptr<BlobDataHandle> another_handle =
- context_->GetBlobDataFromUUID(kId);
- EXPECT_TRUE(another_handle);
-
- // Should disappear after dropping both handles.
- blob_data_handle.reset();
- another_handle.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(context_->registry().HasEntry(kId));
-}
-
TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnStart) {
const std::string kId("id");
// Host deleted after OnStartBuilding.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
-
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element};
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
std::vector<BlobItemBytesRequest> expected_requests = {
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
@@ -845,15 +714,13 @@ TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnMemoryResponse) {
const std::string kId("id");
// Host deleted after OnMemoryItemResponse.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
-
- // Create list of two items.
DataElement element;
element.SetToBytesDescription(kDataSize);
std::vector<DataElement> elements = {element, element};
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+
+ // Create list of two items.
std::vector<BlobItemBytesRequest> expected_requests = {
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize),
BlobItemBytesRequest::CreateIPCRequest(1, 1, 0, kDataSize)};
@@ -878,37 +745,41 @@ TEST_F(BlobDispatcherHostTest, CreateBlobWithBrokenReference) {
// First, let's test a circular reference.
const std::string kCircularId("id1");
- host_->OnRegisterBlobUUID(kCircularId, std::string(kContentType),
- std::string(kContentDisposition), {kCircularId});
+ DataElement element;
+ element.SetToBlob(kCircularId);
+ std::vector<DataElement> elements = {element};
+ host_->OnRegisterBlob(kCircularId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
ExpectAndResetBadMessage();
+ // Remove the blob.
+ host_->OnDecrementBlobRefCount(kCircularId);
+ sink_.ClearMessages();
// Next, test a blob that references a broken blob.
- host_->OnRegisterBlobUUID(kBrokenId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- host_->OnCancelBuildingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN);
+ element.SetToBytesDescription(kDataSize);
+ elements = {element};
+ host_->OnRegisterBlob(kBrokenId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ sink_.ClearMessages();
+ host_->OnCancelBuildingBlob(kBrokenId, BlobStatus::ERR_OUT_OF_MEMORY);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ sink_.ClearMessages();
EXPECT_TRUE(context_->GetBlobDataFromUUID(kBrokenId)->IsBroken());
// Create referencing blob. We should be broken right away, but also ignore
// the subsequent OnStart message.
- host_->OnRegisterBlobUUID(kReferencingId, std::string(kContentType),
- std::string(kContentDisposition), {kBrokenId});
+ element.SetToBytesDescription(kDataSize);
+ elements = {element};
+ element.SetToBlob(kBrokenId);
+ elements.push_back(element);
+ host_->OnRegisterBlob(kReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_TRUE(context_->GetBlobDataFromUUID(kReferencingId)->IsBroken());
EXPECT_FALSE(IsBeingBuiltInHost(kReferencingId));
EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
- ExpectCancel(kReferencingId,
- IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN);
+ ExpectCancel(kReferencingId, BlobStatus::ERR_REFERENCED_BLOB_BROKEN);
sink_.ClearMessages();
-
- DataElement element;
- element.SetToBytesDescription(kDataSize);
- std::vector<DataElement> elements = {element};
- element.SetToBlob(kBrokenId);
- elements.push_back(element);
- host_->OnStartBuildingBlob(kReferencingId, elements);
- EXPECT_EQ(0u, sink_.message_count());
- base::RunLoop().RunUntilIdle();
}
TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) {
@@ -932,66 +803,46 @@ TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) {
// verify that a building message from the renderer will kill it.
// Test OnStartBuilding after double dereference.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
- host2->OnIncrementBlobRefCount(kId);
- host_->OnDecrementBlobRefCount(kId);
- EXPECT_FALSE(host_->IsInUseInHost(kId));
- host2->OnDecrementBlobRefCount(kId);
- // So no more blob in the context, but we're still being built in host 1.
- EXPECT_FALSE(context_->registry().HasEntry(kId));
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
- // We should be cleaned up.
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
- ExpectCancel(kId,
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ ExpectRequest(kId, expected_requests);
sink_.ClearMessages();
-
- // Same as above, but test OnMemoryItemResponse after double dereference.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
host2->OnIncrementBlobRefCount(kId);
host_->OnDecrementBlobRefCount(kId);
EXPECT_FALSE(host_->IsInUseInHost(kId));
- host_->OnStartBuildingBlob(kId, elements);
- ExpectRequest(kId, expected_requests);
- sink_.ClearMessages();
-
host2->OnDecrementBlobRefCount(kId);
- // So no more blob in the context, but we're still being built in host 1.
+ // Blob is gone as we've been decremented from both hosts.
EXPECT_FALSE(context_->registry().HasEntry(kId));
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
+ // Send the memory. When the host sees the entry doesn't exist, it should
+ // cancel and clean up.
+ EXPECT_TRUE(host_->transport_host_.IsBeingBuilt(kId));
host_->OnMemoryItemResponse(kId, responses);
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
// We should be cleaned up.
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
- ExpectCancel(kId,
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kId));
+ ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING);
sink_.ClearMessages();
// Same, but now for OnCancel.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
host2->OnIncrementBlobRefCount(kId);
host_->OnDecrementBlobRefCount(kId);
EXPECT_FALSE(host_->IsInUseInHost(kId));
- host_->OnStartBuildingBlob(kId, elements);
ExpectRequest(kId, expected_requests);
sink_.ClearMessages();
host2->OnDecrementBlobRefCount(kId);
- // So no more blob in the context, but we're still being built in host 1.
+ // Blob is gone as we've been decremented from both hosts.
EXPECT_FALSE(context_->registry().HasEntry(kId));
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_TRUE(host_->transport_host_.IsBeingBuilt(kId));
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
// We should be cleaned up.
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kId));
+ ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING);
}
TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) {
@@ -1000,12 +851,16 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) {
const std::string kDifferentHostReferencingId("id3");
// Data elements for our transfer & checking messages.
DataElement element;
- element.SetToBytes(kData, kDataSize);
- std::vector<DataElement> elements = {element};
+ element.SetToBytesDescription(kDataSize);
DataElement referencing_element;
referencing_element.SetToBlob(kId);
+ std::vector<DataElement> elements = {element};
std::vector<DataElement> referencing_elements = {referencing_element};
- std::set<std::string> referenced_blobs_set = {kId};
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
scoped_refptr<TestableBlobDispatcherHost> host2(
new TestableBlobDispatcherHost(chrome_blob_storage_context_,
@@ -1016,39 +871,44 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) {
// after the referenced blob is finished.
// First we start the referenced blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
EXPECT_TRUE(host_->IsInUseInHost(kId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kId));
// Next we start the referencing blobs in both the same and different host.
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition),
- referenced_blobs_set);
- EXPECT_FALSE(host_->shutdown_for_bad_message_);
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
EXPECT_FALSE(host_->shutdown_for_bad_message_);
ExpectDone(kSameHostReferencingId);
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
sink_.ClearMessages();
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId));
+
// Now the other host.
- host2->OnRegisterBlobUUID(
- kDifferentHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition), referenced_blobs_set);
- EXPECT_FALSE(host2->shutdown_for_bad_message_);
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
EXPECT_FALSE(host2->shutdown_for_bad_message_);
ExpectDone(kDifferentHostReferencingId);
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
sink_.ClearMessages();
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
+ EXPECT_FALSE(
+ host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId));
// Now we finish the first blob, and we expect all blobs to finish.
- host_->OnStartBuildingBlob(kId, elements);
+ host_->OnMemoryItemResponse(kId, responses);
ExpectDone(kId);
// We need to run the message loop to propagate the construction callbacks.
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_FALSE(
+ host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId));
EXPECT_FALSE(
context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
EXPECT_FALSE(
@@ -1058,7 +918,10 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) {
// Finally check that our data is correct in the child elements.
std::unique_ptr<BlobDataHandle> handle =
context_->GetBlobDataFromUUID(kDifferentHostReferencingId);
- ExpectHandleEqualsData(handle.get(), elements);
+ DataElement expected;
+ expected.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> expecteds = {expected};
+ ExpectHandleEqualsData(handle.get(), expecteds);
}
TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) {
@@ -1066,59 +929,73 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) {
const std::string kSameHostReferencingId("id2");
const std::string kDifferentHostReferencingId("id3");
// Data elements for our transfer & checking messages.
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
DataElement referencing_element;
referencing_element.SetToBlob(kId);
+ std::vector<DataElement> elements = {element};
std::vector<DataElement> referencing_elements = {referencing_element};
- std::set<std::string> referenced_blobs_set = {kId};
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
scoped_refptr<TestableBlobDispatcherHost> host2(
new TestableBlobDispatcherHost(chrome_blob_storage_context_,
file_system_context_.get(), &sink_));
// We want to have a blob referencing another blob that is building, both on
- // the same host and a different host. After we cancel the first blob, the
- // others should cancel as well.
+ // the same host and a different host. We should successfully build all blobs
+ // after the referenced blob is finished.
// First we start the referenced blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
EXPECT_TRUE(host_->IsInUseInHost(kId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kId));
// Next we start the referencing blobs in both the same and different host.
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition),
- referenced_blobs_set);
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
ExpectDone(kSameHostReferencingId);
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
sink_.ClearMessages();
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId));
+
// Now the other host.
- host2->OnRegisterBlobUUID(
- kDifferentHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition), referenced_blobs_set);
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
+ EXPECT_FALSE(host2->shutdown_for_bad_message_);
ExpectDone(kDifferentHostReferencingId);
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
sink_.ClearMessages();
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
+ EXPECT_FALSE(
+ host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId));
+
bool built = false;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
context_->GetBlobDataFromUUID(kDifferentHostReferencingId)
->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
// Now we cancel the first blob, and we expect all blobs to cancel.
- host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY);
// We need to run the message loop to propagate the construction callbacks.
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_FALSE(
+ host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId));
EXPECT_TRUE(
context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
EXPECT_TRUE(
context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN, error_code);
+ EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, error_code);
sink_.ClearMessages();
}
@@ -1127,61 +1004,67 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) {
const std::string kSameHostReferencingId("id2");
const std::string kDifferentHostReferencingId("id3");
// Data elements for our transfer & checking messages.
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
DataElement referencing_element;
referencing_element.SetToBlob(kId);
+ std::vector<DataElement> elements = {element};
std::vector<DataElement> referencing_elements = {referencing_element};
- std::set<std::string> referenced_blobs_set = {kId};
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
scoped_refptr<TestableBlobDispatcherHost> host2(
new TestableBlobDispatcherHost(chrome_blob_storage_context_,
file_system_context_.get(), &sink_));
// We want to have a blob referencing another blob that is building, both on
- // the same host and a different host. When we destroy the host, the other
- // blob should cancel, as well as the blob on the other host.
+ // the same host and a different host. We should successfully build all blobs
+ // after the referenced blob is finished.
// First we start the referenced blob.
- host_->OnRegisterBlobUUID(kId, std::string(kContentType),
- std::string(kContentDisposition),
- std::set<std::string>());
+ host_->OnRegisterBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition), elements);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
EXPECT_TRUE(host_->IsInUseInHost(kId));
+ EXPECT_TRUE(IsBeingBuiltInContext(kId));
// Next we start the referencing blobs in both the same and different host.
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition),
- referenced_blobs_set);
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
ExpectDone(kSameHostReferencingId);
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
sink_.ClearMessages();
+
// Now the other host.
- host2->OnRegisterBlobUUID(
- kDifferentHostReferencingId, std::string(kContentType),
- std::string(kContentDisposition), referenced_blobs_set);
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referencing_elements);
+ EXPECT_FALSE(host2->shutdown_for_bad_message_);
ExpectDone(kDifferentHostReferencingId);
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
sink_.ClearMessages();
// Grab handles & add listeners.
bool built = true;
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
std::unique_ptr<BlobDataHandle> blob_handle =
context_->GetBlobDataFromUUID(kId);
blob_handle->RunOnConstructionComplete(
base::Bind(&ConstructionCompletePopulator, &built, &error_code));
bool same_host_built = true;
- IPCBlobCreationCancelCode same_host_error_code =
- IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus same_host_error_code =
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
std::unique_ptr<BlobDataHandle> same_host_blob_handle =
context_->GetBlobDataFromUUID(kSameHostReferencingId);
same_host_blob_handle->RunOnConstructionComplete(base::Bind(
&ConstructionCompletePopulator, &same_host_built, &same_host_error_code));
bool other_host_built = true;
- IPCBlobCreationCancelCode other_host_error_code =
- IPCBlobCreationCancelCode::UNKNOWN;
+ BlobStatus other_host_error_code =
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
std::unique_ptr<BlobDataHandle> other_host_blob_handle =
context_->GetBlobDataFromUUID(kDifferentHostReferencingId);
other_host_blob_handle->RunOnConstructionComplete(
@@ -1192,7 +1075,8 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) {
host_ = nullptr;
// We need to run the message loop to propagate the construction callbacks.
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_FALSE(
+ host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId));
EXPECT_TRUE(
context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
EXPECT_TRUE(
@@ -1200,13 +1084,11 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) {
// Check our callbacks
EXPECT_FALSE(built);
- EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code);
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, error_code);
EXPECT_FALSE(same_host_built);
- EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT,
- same_host_error_code);
+ EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, same_host_error_code);
EXPECT_FALSE(other_host_built);
- EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT,
- other_host_error_code);
+ EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, other_host_error_code);
sink_.ClearMessages();
}
diff --git a/chromium/content/browser/blob_storage/blob_flattener_unittest.cc b/chromium/content/browser/blob_storage/blob_flattener_unittest.cc
new file mode 100644
index 00000000000..3e70dffc124
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_flattener_unittest.cc
@@ -0,0 +1,204 @@
+// 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 "storage/browser/blob/blob_storage_context.h"
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/time/time.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_data_item.h"
+#include "storage/browser/blob/blob_entry.h"
+#include "storage/browser/blob/blob_storage_registry.h"
+#include "storage/browser/blob/shareable_blob_data_item.h"
+#include "storage/common/data_element.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+namespace {
+using base::TestSimpleTaskRunner;
+
+const char kType[] = "type";
+const char kDisposition[] = "";
+
+} // namespace
+
+class BlobFlattenerTest : public testing::Test {
+ protected:
+ using BlobFlattener = BlobStorageContext::BlobFlattener;
+
+ BlobFlattenerTest()
+ : fake_file_path_(base::FilePath(FILE_PATH_LITERAL("kFakePath"))) {}
+ ~BlobFlattenerTest() override {}
+
+ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+
+ void TearDown() override {
+ base::RunLoop().RunUntilIdle();
+ file_runner_->RunPendingTasks();
+ ASSERT_TRUE(temp_dir_.Delete());
+ }
+
+ scoped_refptr<BlobDataItem> CreateDataDescriptionItem(size_t size) {
+ std::unique_ptr<DataElement> element(new DataElement());
+ element->SetToBytesDescription(size);
+ return scoped_refptr<BlobDataItem>(new BlobDataItem(std::move(element)));
+ };
+
+ scoped_refptr<BlobDataItem> CreateDataItem(const char* memory, size_t size) {
+ std::unique_ptr<DataElement> element(new DataElement());
+ element->SetToBytes(memory, size);
+ return scoped_refptr<BlobDataItem>(new BlobDataItem(std::move(element)));
+ };
+
+ scoped_refptr<BlobDataItem> CreateFileItem(size_t offset, size_t size) {
+ std::unique_ptr<DataElement> element(new DataElement());
+ element->SetToFilePathRange(fake_file_path_, offset, size,
+ base::Time::Max());
+ return scoped_refptr<BlobDataItem>(new BlobDataItem(std::move(element)));
+ };
+
+ std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) {
+ BlobDataBuilder builder(id);
+ builder.AppendData("1", 1);
+ builder.set_content_type("text/plain");
+ return context_.AddFinishedBlob(builder);
+ }
+
+ BlobStorageRegistry* registry() { return context_.mutable_registry(); }
+
+ const ShareableBlobDataItem& GetItemInBlob(const std::string& uuid,
+ size_t index) {
+ BlobEntry* entry = registry()->GetEntry(uuid);
+ EXPECT_TRUE(entry);
+ return *entry->items()[index];
+ }
+
+ base::FilePath fake_file_path_;
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
+
+ base::MessageLoop fake_io_message_loop;
+ BlobStorageContext context_;
+};
+
+TEST_F(BlobFlattenerTest, NoBlobItems) {
+ const std::string kBlobUUID = "kId";
+
+ BlobDataBuilder builder(kBlobUUID);
+ builder.AppendData("hi", 2u);
+ builder.AppendFile(fake_file_path_, 0u, 10u, base::Time::Max());
+ BlobEntry output(kType, kDisposition);
+ BlobFlattener flattener(builder, &output, registry());
+
+ EXPECT_EQ(BlobStatus::PENDING_QUOTA, flattener.status);
+ EXPECT_EQ(0u, flattener.dependent_blobs.size());
+ EXPECT_EQ(0u, flattener.copies.size());
+ EXPECT_EQ(12u, flattener.total_size);
+ EXPECT_EQ(2u, flattener.memory_quota_needed);
+
+ ASSERT_EQ(2u, output.items().size());
+ EXPECT_EQ(*CreateDataItem("hi", 2u), *output.items()[0]->item());
+ EXPECT_EQ(*CreateFileItem(0, 10u), *output.items()[1]->item());
+}
+
+TEST_F(BlobFlattenerTest, ErrorCases) {
+ const std::string kBlobUUID = "kId";
+ const std::string kBlob2UUID = "kId2";
+
+ // Invalid blob reference.
+ {
+ BlobDataBuilder builder(kBlobUUID);
+ builder.AppendBlob("doesnotexist");
+ BlobEntry output(kType, kDisposition);
+ BlobFlattener flattener(builder, &output, registry());
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status);
+ }
+
+ // Circular reference.
+ {
+ BlobDataBuilder builder(kBlobUUID);
+ builder.AppendBlob(kBlobUUID);
+ BlobEntry output(kType, kDisposition);
+ BlobFlattener flattener(builder, &output, registry());
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status);
+ }
+
+ // Bad slice.
+ {
+ std::unique_ptr<BlobDataHandle> handle = SetupBasicBlob(kBlob2UUID);
+ BlobDataBuilder builder(kBlobUUID);
+ builder.AppendBlob(kBlob2UUID, 1, 2);
+ BlobEntry output(kType, kDisposition);
+ BlobFlattener flattener(builder, &output, registry());
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status);
+ }
+}
+
+TEST_F(BlobFlattenerTest, BlobWithSlices) {
+ const std::string kBlobUUID = "kId";
+ const std::string kDataBlob = "kId2";
+ const std::string kFileBlob = "kId3";
+
+ // We have the following:
+ // * data,
+ // * sliced data blob,
+ // * file
+ // * full data blob,
+ // * pending data,
+
+ std::unique_ptr<BlobDataHandle> data_blob;
+ {
+ BlobDataBuilder builder(kDataBlob);
+ builder.AppendData("12345", 5);
+ builder.set_content_type("text/plain");
+ data_blob = context_.AddFinishedBlob(builder);
+ }
+
+ std::unique_ptr<BlobDataHandle> file_blob;
+ {
+ BlobDataBuilder builder(kFileBlob);
+ builder.AppendFile(fake_file_path_, 1u, 10u, base::Time::Max());
+ file_blob = context_.AddFinishedBlob(builder);
+ }
+
+ BlobDataBuilder builder(kBlobUUID);
+ builder.AppendData("hi", 2u);
+ builder.AppendBlob(kDataBlob, 1u, 2u);
+ builder.AppendFile(fake_file_path_, 3u, 5u, base::Time::Max());
+ builder.AppendBlob(kDataBlob);
+ builder.AppendBlob(kFileBlob, 1u, 3u);
+ builder.AppendFutureData(12u);
+
+ BlobEntry output(kType, kDisposition);
+ BlobFlattener flattener(builder, &output, registry());
+ EXPECT_EQ(BlobStatus::PENDING_QUOTA, flattener.status);
+
+ EXPECT_EQ(2u, flattener.dependent_blobs.size());
+ EXPECT_EQ(29u, flattener.total_size);
+ EXPECT_EQ(16u, flattener.memory_quota_needed);
+
+ ASSERT_EQ(6u, output.items().size());
+ EXPECT_EQ(*CreateDataItem("hi", 2u), *output.items()[0]->item());
+ EXPECT_EQ(*CreateDataDescriptionItem(2u), *output.items()[1]->item());
+ EXPECT_EQ(*CreateFileItem(3u, 5u), *output.items()[2]->item());
+ EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *output.items()[3]);
+ EXPECT_EQ(*CreateFileItem(2u, 3u), *output.items()[4]->item());
+ EXPECT_EQ(*CreateDataDescriptionItem(12u), *output.items()[5]->item());
+
+ // We're copying item at index 1
+ ASSERT_EQ(1u, flattener.copies.size());
+ EXPECT_EQ(*flattener.copies[0].dest_item, *output.items()[1]);
+ EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *flattener.copies[0].source_item);
+ EXPECT_EQ(1u, flattener.copies[0].source_item_offset);
+}
+
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_memory_controller_unittest.cc b/chromium/content/browser/blob_storage/blob_memory_controller_unittest.cc
new file mode 100644
index 00000000000..290a40be23c
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_memory_controller_unittest.cc
@@ -0,0 +1,680 @@
+// 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 "storage/browser/blob/blob_memory_controller.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_item.h"
+#include "storage/browser/blob/shareable_blob_data_item.h"
+#include "storage/common/data_element.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+using Strategy = BlobMemoryController::Strategy;
+using FileCreationInfo = BlobMemoryController::FileCreationInfo;
+using base::TestSimpleTaskRunner;
+using ItemState = ShareableBlobDataItem::State;
+using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask;
+
+const std::string kBlobStorageDirectory = "blob_storage";
+const size_t kTestBlobStorageIPCThresholdBytes = 20;
+const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
+const size_t kTestBlobStorageMaxBlobMemorySize = 500;
+const uint64_t kTestBlobStorageMaxDiskSpace = 1000;
+const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
+const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+
+class BlobMemoryControllerTest : public testing::Test {
+ protected:
+ BlobMemoryControllerTest() {}
+
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ base::ThreadRestrictions::SetIOAllowed(false);
+ };
+
+ void TearDown() override {
+ files_created_.clear();
+ // Make sure we clean up the files.
+ base::RunLoop().RunUntilIdle();
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ base::ThreadRestrictions::SetIOAllowed(true);
+ ASSERT_TRUE(temp_dir_.Delete());
+ }
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems(
+ const BlobDataBuilder& builder) {
+ std::vector<scoped_refptr<ShareableBlobDataItem>> result;
+ for (size_t i = 0; i < builder.items_.size(); ++i) {
+ result.push_back(make_scoped_refptr(new ShareableBlobDataItem(
+ builder.items_[i], ShareableBlobDataItem::QUOTA_NEEDED)));
+ }
+ return result;
+ }
+
+ void SetTestMemoryLimits(BlobMemoryController* controller) {
+ BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ controller->set_limits_for_testing(limits);
+ }
+
+ void SaveFileCreationInfo(bool success, std::vector<FileCreationInfo> info) {
+ file_quota_result_ = success;
+ if (success) {
+ files_created_.swap(info);
+ }
+ }
+
+ void SaveMemoryRequest(bool success) { memory_quota_result_ = success; }
+
+ BlobMemoryController::FileQuotaRequestCallback GetFileCreationCallback() {
+ return base::Bind(&BlobMemoryControllerTest::SaveFileCreationInfo,
+ base::Unretained(this));
+ }
+
+ BlobMemoryController::MemoryQuotaRequestCallback GetMemoryRequestCallback() {
+ return base::Bind(&BlobMemoryControllerTest::SaveMemoryRequest,
+ base::Unretained(this));
+ }
+
+ void RunFileThreadTasks() {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ file_runner_->RunPendingTasks();
+ base::ThreadRestrictions::SetIOAllowed(false);
+ }
+
+ bool HasMemoryAllocation(ShareableBlobDataItem* item) {
+ return static_cast<bool>(item->memory_allocation_);
+ }
+
+ bool file_quota_result_ = false;
+ base::ScopedTempDir temp_dir_;
+ std::vector<FileCreationInfo> files_created_;
+ bool memory_quota_result_ = false;
+
+ scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
+
+ base::MessageLoop fake_io_message_loop_;
+};
+
+TEST_F(BlobMemoryControllerTest, Strategy) {
+ {
+ BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
+ SetTestMemoryLimits(&controller);
+
+ // No transportation needed.
+ EXPECT_EQ(Strategy::NONE_NEEDED, controller.DetermineStrategy(0, 0));
+
+ // IPC.
+ EXPECT_EQ(Strategy::IPC, controller.DetermineStrategy(
+ 0, kTestBlobStorageIPCThresholdBytes));
+
+ // Shared Memory.
+ EXPECT_EQ(
+ Strategy::SHARED_MEMORY,
+ controller.DetermineStrategy(kTestBlobStorageIPCThresholdBytes,
+ kTestBlobStorageMaxSharedMemoryBytes));
+ EXPECT_EQ(
+ Strategy::SHARED_MEMORY,
+ controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize));
+
+ // Too large.
+ EXPECT_EQ(
+ Strategy::TOO_LARGE,
+ controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize + 1));
+ }
+ {
+ // Enable disk, and check file strategies.
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ EXPECT_EQ(
+ Strategy::SHARED_MEMORY,
+ controller.DetermineStrategy(0, kTestBlobStorageMaxBlobMemorySize -
+ kTestBlobStorageMinFileSizeBytes));
+ EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
+ 0, kTestBlobStorageMaxBlobMemorySize -
+ kTestBlobStorageMinFileSizeBytes + 1));
+
+ EXPECT_EQ(Strategy::FILE, controller.DetermineStrategy(
+ 0, kTestBlobStorageMaxBlobMemorySize));
+
+ // Too large for disk.
+ EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(
+ 0, kTestBlobStorageMaxDiskSpace + 1));
+ }
+}
+
+TEST_F(BlobMemoryControllerTest, GrantMemory) {
+ const std::string kId = "id";
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(10);
+ builder.AppendFutureData(20);
+ builder.AppendFutureData(30);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+ EXPECT_TRUE(memory_quota_result_);
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
+ EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items[1]->state());
+ EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items[2]->state());
+ EXPECT_TRUE(HasMemoryAllocation(items[0].get()));
+}
+
+TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) {
+ const std::string kId = "id";
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ // Add memory item that is the memory quota.
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ base::WeakPtr<QuotaAllocationTask> task =
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+ EXPECT_EQ(nullptr, task);
+ EXPECT_TRUE(memory_quota_result_);
+ memory_quota_result_ = false;
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ items.clear();
+ EXPECT_EQ(0u, controller.memory_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, PageToDisk) {
+ const std::string kId = "id";
+ const std::string kId2 = "id2";
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kData[kTestBlobStorageMaxBlobMemorySize];
+ std::memset(kData, 'e', kTestBlobStorageMaxBlobMemorySize);
+
+ // Add memory item that is the memory quota.
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+ EXPECT_TRUE(memory_quota_result_);
+ memory_quota_result_ = false;
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items[0]->state());
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ // Create an item that is just a little too big.
+ BlobDataBuilder builder2(kId2);
+ builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
+
+ // Reserve memory, which should request successfuly but we can't fit it yet
+ // (no callback).
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
+ CreateSharedDataItems(builder2);
+ base::WeakPtr<QuotaAllocationTask> task =
+ controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
+ EXPECT_NE(nullptr, task);
+ // We don't count the usage yet.
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ EXPECT_FALSE(memory_quota_result_);
+ EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+
+ // Add our original item as populated so it's paged to disk.
+ items[0]->item()->data_element_ptr()->SetToBytes(
+ kData, kTestBlobStorageMaxBlobMemorySize);
+ items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ controller.NotifyMemoryItemsUsed(items);
+
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ // items2 are successfuly allocated.
+ EXPECT_EQ(nullptr, task);
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
+ EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
+ EXPECT_EQ(kTestBlobStorageMinFileSizeBytes + 1, controller.memory_usage());
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
+
+ EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
+
+ items2.clear();
+ EXPECT_EQ(0u, controller.memory_usage());
+ items.clear();
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, controller.disk_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) {
+ const std::string kId = "id";
+ BlobMemoryController controller(temp_dir_.GetPath(), nullptr);
+ SetTestMemoryLimits(&controller);
+
+ EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxBlobMemorySize +
+ kTestBlobStorageMinFileSizeBytes +
+ 1));
+}
+
+TEST_F(BlobMemoryControllerTest, TooLargeForDisk) {
+ const std::string kId = "id";
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1));
+}
+
+TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) {
+ const std::string kId = "id";
+ const std::string kId2 = "id2";
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kData[kTestBlobStorageMaxBlobMemorySize];
+ std::memset(kData, 'e', kTestBlobStorageMaxBlobMemorySize);
+
+ // Add memory item that is the memory quota.
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+
+ // Create an item that is just a little too big.
+ BlobDataBuilder builder2(kId2);
+ builder2.AppendFutureData(kTestBlobStorageMinFileSizeBytes + 1);
+
+ // Reserve memory, which should request successfuly but we can't fit it yet
+ // (no callback).
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
+ CreateSharedDataItems(builder2);
+ base::WeakPtr<QuotaAllocationTask> task =
+ controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
+ // We don't count the usage yet.
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ // Add our original item as populated so we start paging to disk.
+ items[0]->item()->data_element_ptr()->SetToBytes(
+ kData, kTestBlobStorageMaxBlobMemorySize);
+ items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ controller.NotifyMemoryItemsUsed(items);
+
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ EXPECT_TRUE(task);
+
+ task->Cancel();
+ EXPECT_FALSE(task);
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(ItemState::QUOTA_REQUESTED, items2[0]->state());
+ EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
+ EXPECT_EQ(0u, controller.memory_usage());
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.disk_usage());
+
+ items.clear();
+ // Run cleanup tasks from the ShareableFileReferences.
+ base::RunLoop().RunUntilIdle();
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0u, controller.disk_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, FileRequest) {
+ const std::string kId = "id";
+ const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
+
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kData[kBlobSize];
+ std::memset(kData, 'e', kBlobSize);
+
+ // Add item that is the file quota.
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureFile(0, kBlobSize, 0);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ file_quota_result_ = false;
+ base::WeakPtr<QuotaAllocationTask> task =
+ controller.ReserveFileQuota(items, GetFileCreationCallback());
+ EXPECT_TRUE(task);
+ EXPECT_FALSE(file_quota_result_);
+ EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ EXPECT_EQ(0u, controller.memory_usage());
+ EXPECT_EQ(kBlobSize, controller.disk_usage());
+
+ EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace));
+
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(file_quota_result_);
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+ EXPECT_FALSE(task);
+
+ // Do the work to populate the file.
+ EXPECT_EQ(1u, files_created_.size());
+ EXPECT_TRUE(
+ builder.PopulateFutureFile(0, std::move(files_created_[0].file_reference),
+ files_created_[0].last_modified));
+ base::ThreadRestrictions::SetIOAllowed(true);
+ files_created_.clear();
+ base::ThreadRestrictions::SetIOAllowed(false);
+ EXPECT_EQ(DataElement::TYPE_FILE, items[0]->item()->type());
+ EXPECT_FALSE(
+ BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element()));
+
+ builder.Clear();
+ items.clear();
+ // Run cleanup tasks from the ShareableFileReferences.
+ base::RunLoop().RunUntilIdle();
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0u, controller.disk_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, CancelFileRequest) {
+ const std::string kId = "id";
+ const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1;
+
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kData[kBlobSize];
+ std::memset(kData, 'e', kBlobSize);
+
+ // Add memory item that is the memory quota.
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureFile(0, kBlobSize, 0);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ base::WeakPtr<QuotaAllocationTask> task =
+ controller.ReserveFileQuota(items, GetFileCreationCallback());
+ EXPECT_TRUE(task);
+ EXPECT_EQ(ItemState::QUOTA_REQUESTED, items[0]->state());
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ EXPECT_EQ(0u, controller.memory_usage());
+ EXPECT_EQ(kBlobSize, controller.disk_usage());
+
+ task->Cancel();
+ EXPECT_FALSE(task);
+ EXPECT_EQ(kBlobSize, controller.disk_usage());
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, controller.disk_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) {
+ const std::string kId1 = "id";
+ const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes;
+ char kData1[kSize1];
+ std::memset(kData1, 'e', kSize1);
+
+ const std::string kId2 = "id2";
+ const size_t kSize2 = kTestBlobStorageMaxFileSizeBytes;
+ char kData2[kSize2];
+ std::memset(kData2, 'f', kSize2);
+
+ const std::string kId3 = "id3";
+ const size_t kSize3 = kTestBlobStorageMaxBlobMemorySize - 1;
+
+ // Assert we shouldn't trigger paging preemptively.
+ ASSERT_LE(kSize1 + kSize2, kTestBlobStorageMaxBlobMemorySize);
+
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ // We add two items that should be their own files when we page to disk, and
+ // then add the last item to trigger the paging.
+
+ BlobDataBuilder builder1(kId1);
+ builder1.AppendFutureData(kSize1);
+ BlobDataBuilder builder2(kId2);
+ builder2.AppendFutureData(kSize2);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items1 =
+ CreateSharedDataItems(builder1);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
+ CreateSharedDataItems(builder2);
+
+ memory_quota_result_ = false;
+ controller.ReserveMemoryQuota(items1, GetMemoryRequestCallback());
+ EXPECT_TRUE(memory_quota_result_);
+ memory_quota_result_ = false;
+ controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
+ EXPECT_TRUE(memory_quota_result_);
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items1[0]->state());
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items2[0]->state());
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+ EXPECT_EQ(kSize1 + kSize2, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ // Create an item that is too big.
+ BlobDataBuilder builder3(kId3);
+ builder3.AppendFutureData(kSize3);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items3 =
+ CreateSharedDataItems(builder3);
+ memory_quota_result_ = false;
+ controller.ReserveMemoryQuota(items3, GetMemoryRequestCallback());
+ EXPECT_FALSE(memory_quota_result_);
+
+ EXPECT_EQ(ItemState::QUOTA_REQUESTED, items3[0]->state());
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+
+ // Add our original item as populated so it's paged to disk.
+ items1[0]->item()->data_element_ptr()->SetToBytes(kData1, kSize1);
+ items1[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ items2[0]->item()->data_element_ptr()->SetToBytes(kData2, kSize2);
+ items2[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> both_items = {items1[0],
+ items2[0]};
+ controller.NotifyMemoryItemsUsed(both_items);
+ both_items.clear();
+
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(memory_quota_result_);
+ EXPECT_EQ(ItemState::QUOTA_GRANTED, items3[0]->state());
+ EXPECT_EQ(DataElement::TYPE_FILE, items1[0]->item()->type());
+ EXPECT_EQ(DataElement::TYPE_FILE, items2[0]->item()->type());
+ EXPECT_NE(items1[0]->item()->path(), items2[0]->item()->path());
+ EXPECT_EQ(kSize3, controller.memory_usage());
+ EXPECT_EQ(kSize1 + kSize2, controller.disk_usage());
+
+ items1.clear();
+ items2.clear();
+ items3.clear();
+
+ EXPECT_EQ(0u, controller.memory_usage());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, controller.disk_usage());
+}
+
+TEST_F(BlobMemoryControllerTest, FullEviction) {
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kData[1];
+ kData[0] = 'e';
+
+ // Create a bunch of small stuff.
+ std::vector<scoped_refptr<ShareableBlobDataItem>> small_items;
+ for (size_t i = 0;
+ i < kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes;
+ i++) {
+ BlobDataBuilder builder("fake");
+ builder.AppendData(kData, 1);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+ base::WeakPtr<QuotaAllocationTask> memory_task =
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+ EXPECT_FALSE(memory_task);
+ items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ small_items.insert(small_items.end(), items.begin(), items.end());
+ }
+ controller.NotifyMemoryItemsUsed(small_items);
+ EXPECT_FALSE(file_runner_->HasPendingTask());
+ EXPECT_EQ(
+ kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
+ controller.memory_usage());
+
+ // Create maximum size blob to evict ALL small stuff.
+ BlobDataBuilder builder("fake");
+ builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize -
+ kTestBlobStorageMinFileSizeBytes);
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ memory_quota_result_ = false;
+ base::WeakPtr<QuotaAllocationTask> memory_task =
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+ EXPECT_TRUE(memory_task);
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(
+ kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
+ controller.memory_usage());
+ EXPECT_EQ(
+ kTestBlobStorageMaxBlobMemorySize - kTestBlobStorageMinFileSizeBytes,
+ controller.disk_usage());
+
+ EXPECT_TRUE(memory_quota_result_);
+}
+
+TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) {
+ const std::string kFirstMemoryId = "id";
+ const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize;
+ const std::string kSecondMemoryId = "id2";
+ const uint64_t kSecondMemorySize = 1;
+ const std::string kFileId = "id2";
+ const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize;
+
+ BlobMemoryController controller(temp_dir_.GetPath(), file_runner_);
+ SetTestMemoryLimits(&controller);
+
+ char kDataMemoryData[kFirstMemorySize];
+ std::memset(kDataMemoryData, 'e', kFirstMemorySize);
+
+ // Add first memory item to fill up some memory quota.
+ BlobDataBuilder builder(kFirstMemoryId);
+ builder.AppendFutureData(kTestBlobStorageMaxBlobMemorySize);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items =
+ CreateSharedDataItems(builder);
+
+ controller.ReserveMemoryQuota(items, GetMemoryRequestCallback());
+
+ // Create a second memory item that is just a little too big.
+ BlobDataBuilder builder2(kSecondMemoryId);
+ builder2.AppendFutureData(kSecondMemorySize);
+
+ // Reserve memory, which should request successfuly but we can't fit it yet.
+ std::vector<scoped_refptr<ShareableBlobDataItem>> items2 =
+ CreateSharedDataItems(builder2);
+ base::WeakPtr<QuotaAllocationTask> memory_task =
+ controller.ReserveMemoryQuota(items2, GetMemoryRequestCallback());
+ // We don't count the usage yet.
+ EXPECT_EQ(kTestBlobStorageMaxBlobMemorySize, controller.memory_usage());
+ EXPECT_EQ(0u, controller.disk_usage());
+
+ // Add our original item as populated so we start paging it to disk.
+ items[0]->item()->data_element_ptr()->SetToBytes(kDataMemoryData,
+ kFirstMemorySize);
+ items[0]->set_state(ItemState::POPULATED_WITH_QUOTA);
+ controller.NotifyMemoryItemsUsed(items);
+
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+ EXPECT_TRUE(memory_task);
+ EXPECT_EQ(kFirstMemorySize, controller.disk_usage());
+
+ // Add our file item now.
+ BlobDataBuilder file_builder(kFileId);
+ file_builder.AppendFutureFile(0, kFileBlobSize, 0);
+
+ std::vector<scoped_refptr<ShareableBlobDataItem>> file_items =
+ CreateSharedDataItems(file_builder);
+
+ base::WeakPtr<QuotaAllocationTask> file_task =
+ controller.ReserveFileQuota(file_items, GetFileCreationCallback());
+ EXPECT_TRUE(file_task);
+ EXPECT_TRUE(file_runner_->HasPendingTask());
+
+ // We should have both memory paging tasks and file paging tasks.
+ EXPECT_EQ(kFirstMemorySize, controller.memory_usage());
+ EXPECT_EQ(kFirstMemorySize + kFileBlobSize, controller.disk_usage());
+ file_quota_result_ = true;
+ memory_quota_result_ = true;
+
+ files_created_.clear();
+
+ // Disable paging! This should cancel all file-related tasks and leave us with
+ // only the first memory item.
+ controller.DisableFilePaging(base::File::FILE_ERROR_FAILED);
+ EXPECT_FALSE(file_quota_result_);
+ EXPECT_FALSE(memory_quota_result_);
+ EXPECT_FALSE(file_task);
+ EXPECT_FALSE(memory_task);
+
+ file_items.clear();
+ items.clear();
+
+ RunFileThreadTasks();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0ull, controller.disk_usage());
+ EXPECT_EQ(0ull, controller.memory_usage());
+}
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_reader_unittest.cc b/chromium/content/browser/blob_storage/blob_reader_unittest.cc
index dd519a09465..399af8f4731 100644
--- a/chromium/content/browser/blob_storage/blob_reader_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_reader_unittest.cc
@@ -43,6 +43,7 @@ using base::FilePath;
using content::AsyncFileTestHelper;
using net::DrainableIOBuffer;
using net::IOBuffer;
+using FileCreationInfo = storage::BlobMemoryController::FileCreationInfo;
namespace storage {
namespace {
@@ -50,6 +51,16 @@ namespace {
const int kTestDiskCacheStreamIndex = 0;
const int kTestDiskCacheSideStreamIndex = 1;
+void SaveBlobStatusAndFiles(BlobStatus* status_ptr,
+ std::vector<FileCreationInfo>* files_ptr,
+ BlobStatus status,
+ std::vector<FileCreationInfo> files) {
+ *status_ptr = status;
+ for (FileCreationInfo& info : files) {
+ files_ptr->push_back(std::move(info));
+ }
+}
+
// Our disk cache tests don't need a real data handle since the tests themselves
// scope the disk cache and entries.
class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
@@ -909,8 +920,7 @@ TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) {
FilePath path = kPathBase.Append(
FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
uint64_t offset = i % 3 == 0 ? 1 : 0;
- uint64_t size =
- i % 2 == 0 ? kItemSize : std::numeric_limits<uint64_t>::max();
+ uint64_t size = kItemSize;
b.AppendFile(path, offset, size, kTime);
}
this->InitializeReader(&b);
@@ -1174,9 +1184,17 @@ TEST_F(BlobReaderTest, RangeError) {
TEST_F(BlobReaderTest, HandleBeforeAsyncCancel) {
const std::string kUuid("uuid1");
+ const std::string kData("Hello!!!");
+ const size_t kDataSize = 8ul;
+ std::vector<FileCreationInfo> files;
- context_.CreatePendingBlob(kUuid, "", "");
- blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
+ BlobDataBuilder b(kUuid);
+ b.AppendFutureData(kDataSize);
+ BlobStatus can_populate_status =
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ blob_handle_ = context_.BuildBlob(
+ b, base::Bind(&SaveBlobStatusAndFiles, &can_populate_status, &files));
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, can_populate_status);
provider_ = new MockFileStreamReaderProvider();
reader_.reset(new BlobReader(blob_handle_.get(), base::WrapUnique(provider_),
message_loop_.task_runner().get()));
@@ -1184,7 +1202,8 @@ TEST_F(BlobReaderTest, HandleBeforeAsyncCancel) {
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
EXPECT_FALSE(reader_->IsInMemory());
- context_.CancelPendingBlob(kUuid, IPCBlobCreationCancelCode::UNKNOWN);
+ context_.CancelBuildingBlob(kUuid,
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(net::ERR_FAILED, size_result);
}
@@ -1193,11 +1212,15 @@ TEST_F(BlobReaderTest, ReadFromIncompleteBlob) {
const std::string kUuid("uuid1");
const std::string kData("Hello!!!");
const size_t kDataSize = 8ul;
+ std::vector<FileCreationInfo> files;
BlobDataBuilder b(kUuid);
- b.AppendData(kData);
- context_.CreatePendingBlob(kUuid, "", "");
- blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
+ b.AppendFutureData(kDataSize);
+ BlobStatus can_populate_status =
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ blob_handle_ = context_.BuildBlob(
+ b, base::Bind(&SaveBlobStatusAndFiles, &can_populate_status, &files));
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, can_populate_status);
provider_ = new MockFileStreamReaderProvider();
reader_.reset(new BlobReader(blob_handle_.get(), base::WrapUnique(provider_),
message_loop_.task_runner().get()));
@@ -1205,7 +1228,8 @@ TEST_F(BlobReaderTest, ReadFromIncompleteBlob) {
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
EXPECT_FALSE(reader_->IsInMemory());
- context_.CompletePendingBlob(b);
+ b.PopulateFutureData(0, kData.data(), 0, kDataSize);
+ context_.NotifyTransportComplete(kUuid);
base::RunLoop().RunUntilIdle();
CheckSizeCalculatedAsynchronously(kDataSize, size_result);
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
diff --git a/chromium/content/browser/blob_storage/blob_slice_unittest.cc b/chromium/content/browser/blob_storage/blob_slice_unittest.cc
new file mode 100644
index 00000000000..e7266fd3554
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_slice_unittest.cc
@@ -0,0 +1,195 @@
+// 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 "storage/browser/blob/blob_storage_context.h"
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_item.h"
+#include "storage/browser/blob/blob_entry.h"
+#include "storage/browser/blob/shareable_blob_data_item.h"
+#include "storage/common/data_element.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+namespace {
+const char kType[] = "type";
+const char kDisposition[] = "";
+} // namespace
+
+class BlobSliceTest : public testing::Test {
+ protected:
+ using BlobSlice = BlobStorageContext::BlobSlice;
+
+ BlobSliceTest() {}
+ ~BlobSliceTest() override {}
+
+ scoped_refptr<ShareableBlobDataItem> CreateDataItem(size_t size) {
+ std::unique_ptr<DataElement> element(new DataElement());
+ element->SetToAllocatedBytes(size);
+ for (size_t i = 0; i < size; i++) {
+ *(element->mutable_bytes() + i) = i;
+ }
+ return scoped_refptr<ShareableBlobDataItem>(
+ new ShareableBlobDataItem(new BlobDataItem(std::move(element)),
+ ShareableBlobDataItem::QUOTA_NEEDED));
+ };
+
+ scoped_refptr<ShareableBlobDataItem> CreateFileItem(size_t offset,
+ size_t size) {
+ std::unique_ptr<DataElement> element(new DataElement());
+ element->SetToFilePathRange(base::FilePath(FILE_PATH_LITERAL("kFakePath")),
+ offset, size, base::Time::Max());
+ return scoped_refptr<ShareableBlobDataItem>(new ShareableBlobDataItem(
+ new BlobDataItem(std::move(element)),
+ ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA));
+ };
+
+ void ExpectFirstSlice(const BlobSlice& slice,
+ scoped_refptr<ShareableBlobDataItem> source_item,
+ size_t first_item_slice_offset,
+ size_t size) {
+ EXPECT_TRUE(slice.first_source_item);
+ EXPECT_EQ(first_item_slice_offset, slice.first_item_slice_offset);
+
+ ASSERT_LE(1u, slice.dest_items.size());
+ const DataElement& dest_element =
+ slice.dest_items[0]->item()->data_element();
+
+ EXPECT_EQ(DataElement::TYPE_BYTES_DESCRIPTION, dest_element.type());
+ EXPECT_EQ(static_cast<uint64_t>(size), dest_element.length());
+
+ EXPECT_EQ(*source_item, *slice.first_source_item);
+ }
+
+ void ExpectLastSlice(const BlobSlice& slice,
+ scoped_refptr<ShareableBlobDataItem> source_item,
+ size_t size) {
+ EXPECT_TRUE(slice.last_source_item);
+
+ ASSERT_LE(2u, slice.dest_items.size());
+ const DataElement& dest_element =
+ slice.dest_items.back()->item()->data_element();
+
+ EXPECT_EQ(DataElement::TYPE_BYTES_DESCRIPTION, dest_element.type());
+ EXPECT_EQ(static_cast<uint64_t>(size), dest_element.length());
+
+ EXPECT_EQ(*source_item, *slice.last_source_item);
+ }
+};
+
+TEST_F(BlobSliceTest, FullItem) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize = 5u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item = CreateDataItem(kSize);
+ data.AppendSharedBlobItem(item);
+
+ BlobSlice slice(data, 0, 5);
+ EXPECT_EQ(0u, slice.copying_memory_size.ValueOrDie());
+ EXPECT_FALSE(slice.first_source_item);
+ EXPECT_FALSE(slice.last_source_item);
+ EXPECT_FALSE(slice.first_source_item);
+ EXPECT_FALSE(slice.last_source_item);
+ ASSERT_EQ(1u, slice.dest_items.size());
+ EXPECT_EQ(item, slice.dest_items[0]);
+}
+
+TEST_F(BlobSliceTest, SliceSingleItem) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize = 5u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item = CreateDataItem(kSize);
+ data.AppendSharedBlobItem(item);
+
+ BlobSlice slice(data, 1, 3);
+ EXPECT_EQ(3u, slice.copying_memory_size.ValueOrDie());
+ EXPECT_FALSE(slice.last_source_item);
+ ExpectFirstSlice(slice, item, 1, 3);
+ ASSERT_EQ(1u, slice.dest_items.size());
+}
+
+TEST_F(BlobSliceTest, SliceSingleLastItem) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize1 = 5u;
+ const size_t kSize2 = 10u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item1 = CreateDataItem(kSize1);
+ scoped_refptr<ShareableBlobDataItem> item2 = CreateDataItem(kSize2);
+ data.AppendSharedBlobItem(item1);
+ data.AppendSharedBlobItem(item2);
+
+ BlobSlice slice(data, 6, 2);
+ EXPECT_EQ(2u, slice.copying_memory_size.ValueOrDie());
+ ExpectFirstSlice(slice, item2, 1, 2);
+ ASSERT_EQ(1u, slice.dest_items.size());
+}
+
+TEST_F(BlobSliceTest, SliceAcrossTwoItems) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize1 = 5u;
+ const size_t kSize2 = 10u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item1 = CreateDataItem(kSize1);
+ scoped_refptr<ShareableBlobDataItem> item2 = CreateDataItem(kSize2);
+ data.AppendSharedBlobItem(item1);
+ data.AppendSharedBlobItem(item2);
+
+ BlobSlice slice(data, 4, 10);
+ EXPECT_EQ(10u, slice.copying_memory_size.ValueOrDie());
+ ExpectFirstSlice(slice, item1, 4, 1);
+ ExpectLastSlice(slice, item2, 9);
+ ASSERT_EQ(2u, slice.dest_items.size());
+}
+
+TEST_F(BlobSliceTest, SliceFileAndLastItem) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize1 = 5u;
+ const size_t kSize2 = 10u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item1 = CreateFileItem(0u, kSize1);
+ scoped_refptr<ShareableBlobDataItem> item2 = CreateDataItem(kSize2);
+ data.AppendSharedBlobItem(item1);
+ data.AppendSharedBlobItem(item2);
+
+ BlobSlice slice(data, 4, 2);
+ EXPECT_EQ(1u, slice.copying_memory_size.ValueOrDie());
+ EXPECT_FALSE(slice.first_source_item);
+ ExpectLastSlice(slice, item2, 1);
+ ASSERT_EQ(2u, slice.dest_items.size());
+
+ EXPECT_EQ(*CreateFileItem(4u, 1u)->item(), *slice.dest_items[0]->item());
+}
+
+TEST_F(BlobSliceTest, SliceAcrossLargeItem) {
+ const std::string kBlobUUID = "kId";
+ const size_t kSize1 = 5u;
+ const size_t kSize2 = 10u;
+ const size_t kSize3 = 10u;
+
+ BlobEntry data(kType, kDisposition);
+ scoped_refptr<ShareableBlobDataItem> item1 = CreateDataItem(kSize1);
+ scoped_refptr<ShareableBlobDataItem> item2 = CreateFileItem(0u, kSize2);
+ scoped_refptr<ShareableBlobDataItem> item3 = CreateDataItem(kSize3);
+ data.AppendSharedBlobItem(item1);
+ data.AppendSharedBlobItem(item2);
+ data.AppendSharedBlobItem(item3);
+
+ BlobSlice slice(data, 2, 20);
+ EXPECT_EQ(3u + 7u, slice.copying_memory_size.ValueOrDie());
+ ExpectFirstSlice(slice, item1, 2, 3);
+ ExpectLastSlice(slice, item3, 7);
+ ASSERT_EQ(3u, slice.dest_items.size());
+
+ EXPECT_EQ(*item2, *slice.dest_items[1]);
+}
+
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_storage_context_unittest.cc b/chromium/content/browser/blob_storage/blob_storage_context_unittest.cc
index e03d5f3b74a..166509e7c53 100644
--- a/chromium/content/browser/blob_storage/blob_storage_context_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_storage_context_unittest.cc
@@ -10,11 +10,16 @@
#include <memory>
#include <string>
+#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/blob_storage/blob_dispatcher_host.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -22,26 +27,33 @@
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/disk_cache.h"
-#include "storage/browser/blob/blob_async_builder_host.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_data_item.h"
#include "storage/browser/blob/blob_data_snapshot.h"
-#include "storage/browser/blob/blob_transport_result.h"
+#include "storage/browser/blob/blob_transport_host.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "testing/gtest/include/gtest/gtest.h"
-using RequestMemoryCallback =
- storage::BlobAsyncBuilderHost::RequestMemoryCallback;
+using RequestMemoryCallback = storage::BlobTransportHost::RequestMemoryCallback;
+using FileCreationInfo = storage::BlobMemoryController::FileCreationInfo;
namespace storage {
namespace {
+using base::TestSimpleTaskRunner;
-const char kContentType[] = "text/plain";
-const char kContentDisposition[] = "content_disposition";
const int kTestDiskCacheStreamIndex = 0;
+const std::string kBlobStorageDirectory = "blob_storage";
+const size_t kTestBlobStorageIPCThresholdBytes = 20;
+const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
+
+const size_t kTestBlobStorageMaxBlobMemorySize = 400;
+const uint64_t kTestBlobStorageMaxDiskSpace = 4000;
+const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
+const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+
// Our disk cache tests don't need a real data handle since the tests themselves
// scope the disk cache and entries.
class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
@@ -79,6 +91,19 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
return entry;
}
+void SaveBlobStatus(BlobStatus* status_ptr, BlobStatus status) {
+ *status_ptr = status;
+}
+
+void SaveBlobStatusAndFiles(BlobStatus* status_ptr,
+ std::vector<FileCreationInfo>* files_ptr,
+ BlobStatus status,
+ std::vector<FileCreationInfo> files) {
+ *status_ptr = status;
+ for (FileCreationInfo& info : files) {
+ files_ptr->push_back(std::move(info));
+ }
+}
} // namespace
@@ -87,58 +112,202 @@ class BlobStorageContextTest : public testing::Test {
BlobStorageContextTest() {}
~BlobStorageContextTest() override {}
+ void SetUp() override { context_ = base::MakeUnique<BlobStorageContext>(); }
+
std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) {
BlobDataBuilder builder(id);
builder.AppendData("1", 1);
builder.set_content_type("text/plain");
- return context_.AddFinishedBlob(builder);
+ return context_->AddFinishedBlob(builder);
+ }
+
+ void SetTestMemoryLimits() {
+ BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ context_->mutable_memory_controller()->set_limits_for_testing(limits);
+ }
+
+ void IncrementRefCount(const std::string& uuid) {
+ context_->IncrementBlobRefCount(uuid);
+ }
+
+ void DecrementRefCount(const std::string& uuid) {
+ context_->DecrementBlobRefCount(uuid);
}
- BlobStorageContext context_;
+ std::vector<FileCreationInfo> files_;
+
+ base::MessageLoop fake_io_message_loop_;
+ std::unique_ptr<BlobStorageContext> context_;
};
-TEST_F(BlobStorageContextTest, IncrementDecrementRef) {
- base::MessageLoop fake_io_message_loop;
+TEST_F(BlobStorageContextTest, BuildBlobAsync) {
+ const std::string kId("id");
+ const size_t kSize = 10u;
+ BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(kSize);
+ builder.set_content_type("text/plain");
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+ std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
+ builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_));
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
+ EXPECT_TRUE(handle->IsBeingBuilt())
+ << static_cast<int>(handle->GetBlobStatus());
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status);
+
+ BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ handle->RunOnConstructionComplete(
+ base::Bind(&SaveBlobStatus, &construction_done));
+
+ EXPECT_EQ(10u, context_->memory_controller().memory_usage());
+
+ builder.PopulateFutureData(0, "abcdefghij", 0, 10u);
+ context_->NotifyTransportComplete(kId);
+
+ // Check we're done.
+ EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(BlobStatus::DONE, construction_done);
+
+ EXPECT_EQ(builder, *handle->CreateSnapshot());
+
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+}
+
+TEST_F(BlobStorageContextTest, BuildBlobAndCancel) {
+ const std::string kId("id");
+ const size_t kSize = 10u;
+ BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+
+ BlobDataBuilder builder(kId);
+ builder.AppendFutureData(kSize);
+ builder.set_content_type("text/plain");
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+ std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
+ builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_));
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
+ EXPECT_TRUE(handle->IsBeingBuilt());
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status);
+ EXPECT_EQ(10u, context_->memory_controller().memory_usage());
+
+ BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ handle->RunOnConstructionComplete(
+ base::Bind(&SaveBlobStatus, &construction_done));
+
+ context_->CancelBuildingBlob(kId, BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT);
+ EXPECT_TRUE(handle->IsBroken());
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+
+ // Check we're broken.
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, handle->GetBlobStatus());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, construction_done);
+}
+
+TEST_F(BlobStorageContextTest, CancelledReference) {
+ const std::string kId1("id1");
+ const std::string kId2("id2");
+ const size_t kSize = 10u;
+ BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+
+ // Start our first blob.
+ BlobDataBuilder builder(kId1);
+ builder.AppendFutureData(kSize);
+ builder.set_content_type("text/plain");
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+ std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob(
+ builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_));
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
+ EXPECT_TRUE(handle->IsBeingBuilt());
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status);
+
+ BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ handle->RunOnConstructionComplete(
+ base::Bind(&SaveBlobStatus, &construction_done));
+
+ EXPECT_EQ(10u, context_->memory_controller().memory_usage());
+
+ // Create our second blob, which depends on the first.
+ BlobDataBuilder builder2(kId2);
+ builder2.AppendBlob(kId1);
+ builder2.set_content_type("text/plain");
+ std::unique_ptr<BlobDataHandle> handle2 = context_->BuildBlob(
+ builder2, BlobStorageContext::TransportAllowedCallback());
+ BlobStatus construction_done2 =
+ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ handle->RunOnConstructionComplete(
+ base::Bind(&SaveBlobStatus, &construction_done2));
+ EXPECT_TRUE(handle2->IsBeingBuilt());
+
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
+
+ // Cancel the first blob.
+ context_->CancelBuildingBlob(kId1, BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT);
+
+ base::RunLoop().RunUntilIdle();
+ // Check we broke successfully.
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, construction_done);
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, handle->GetBlobStatus());
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+ EXPECT_TRUE(handle->IsBroken());
+
+ // Check that it propagated.
+ EXPECT_TRUE(handle2->IsBroken());
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, construction_done2);
+ EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, handle->GetBlobStatus());
+}
+
+TEST_F(BlobStorageContextTest, IncorrectSlice) {
+ const std::string kId1("id1");
+ const std::string kId2("id2");
+
+ std::unique_ptr<BlobDataHandle> handle = SetupBasicBlob(kId1);
+
+ EXPECT_EQ(1lu, context_->memory_controller().memory_usage());
+
+ BlobDataBuilder builder(kId2);
+ builder.AppendBlob(kId1, 1, 10);
+ std::unique_ptr<BlobDataHandle> handle2 = context_->BuildBlob(
+ builder, BlobStorageContext::TransportAllowedCallback());
+
+ EXPECT_TRUE(handle2->IsBroken());
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
+ handle2->GetBlobStatus());
+}
+TEST_F(BlobStorageContextTest, IncrementDecrementRef) {
// Build up a basic blob.
const std::string kId("id");
std::unique_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId);
// Do an extra increment to keep it around after we kill the handle.
- context_.IncrementBlobRefCount(kId);
- context_.IncrementBlobRefCount(kId);
- context_.DecrementBlobRefCount(kId);
- blob_data_handle = context_.GetBlobDataFromUUID(kId);
+ IncrementRefCount(kId);
+ IncrementRefCount(kId);
+ DecrementRefCount(kId);
+ blob_data_handle = context_->GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(context_.registry().HasEntry(kId));
- context_.DecrementBlobRefCount(kId);
- EXPECT_FALSE(context_.registry().HasEntry(kId));
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ DecrementRefCount(kId);
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
// Make sure it goes away in the end.
- blob_data_handle = context_.GetBlobDataFromUUID(kId);
+ blob_data_handle = context_->GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle);
}
-TEST_F(BlobStorageContextTest, OnCancelBuildingBlob) {
- base::MessageLoop fake_io_message_loop;
-
- // Build up a basic blob.
- const std::string kId("id");
- context_.CreatePendingBlob(kId, std::string(kContentType),
- std::string(kContentDisposition));
- EXPECT_TRUE(context_.IsBeingBuilt(kId));
- context_.CancelPendingBlob(kId, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
- EXPECT_TRUE(context_.registry().HasEntry(kId));
- EXPECT_FALSE(context_.IsBeingBuilt(kId));
- EXPECT_TRUE(context_.IsBroken(kId));
-}
-
TEST_F(BlobStorageContextTest, BlobDataHandle) {
- base::MessageLoop fake_io_message_loop;
-
// Build up a basic blob.
const std::string kId("id");
std::unique_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId);
@@ -146,19 +315,19 @@ TEST_F(BlobStorageContextTest, BlobDataHandle) {
// Get another handle
std::unique_ptr<BlobDataHandle> another_handle =
- context_.GetBlobDataFromUUID(kId);
+ context_->GetBlobDataFromUUID(kId);
EXPECT_TRUE(another_handle);
// Should disappear after dropping both handles.
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(context_.registry().HasEntry(kId));
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
another_handle.reset();
base::RunLoop().RunUntilIdle();
- blob_data_handle = context_.GetBlobDataFromUUID(kId);
+ blob_data_handle = context_->GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle);
}
@@ -166,8 +335,6 @@ TEST_F(BlobStorageContextTest, MemoryUsage) {
const std::string kId1("id1");
const std::string kId2("id2");
- base::MessageLoop fake_io_message_loop;
-
BlobDataBuilder builder1(kId1);
BlobDataBuilder builder2(kId2);
builder1.AppendData("Data1Data2");
@@ -179,41 +346,37 @@ TEST_F(BlobStorageContextTest, MemoryUsage) {
builder2.AppendBlob(kId1);
builder2.AppendBlob(kId1);
- EXPECT_EQ(0lu, context_.memory_usage());
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_.AddFinishedBlob(&builder1);
- EXPECT_EQ(10lu, context_.memory_usage());
+ context_->AddFinishedBlob(&builder1);
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
std::unique_ptr<BlobDataHandle> blob_data_handle2 =
- context_.AddFinishedBlob(&builder2);
- EXPECT_EQ(10lu, context_.memory_usage());
+ context_->AddFinishedBlob(&builder2);
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
- EXPECT_EQ(2u, context_.registry().blob_count());
+ EXPECT_EQ(2u, context_->registry().blob_count());
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(10lu, context_.memory_usage());
- EXPECT_EQ(1u, context_.registry().blob_count());
+ EXPECT_EQ(10lu, context_->memory_controller().memory_usage());
+ EXPECT_EQ(1u, context_->registry().blob_count());
blob_data_handle2.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0lu, context_.memory_usage());
- EXPECT_EQ(0u, context_.registry().blob_count());
+ EXPECT_EQ(0lu, context_->memory_controller().memory_usage());
+ EXPECT_EQ(0u, context_->registry().blob_count());
}
TEST_F(BlobStorageContextTest, AddFinishedBlob) {
const std::string kId1("id1");
const std::string kId2("id12");
- const std::string kId2Prime("id2.prime");
const std::string kId3("id3");
- const std::string kId3Prime("id3.prime");
-
- base::MessageLoop fake_io_message_loop;
BlobDataBuilder builder1(kId1);
BlobDataBuilder builder2(kId2);
- BlobDataBuilder canonicalized_blob_data2(kId2Prime);
+ BlobDataBuilder canonicalized_blob_data2(kId2);
builder1.AppendData("Data1Data2");
builder2.AppendBlob(kId1, 5, 5);
builder2.AppendData(" is the best");
@@ -223,9 +386,11 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob) {
BlobStorageContext context;
std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_.AddFinishedBlob(&builder1);
+ context_->AddFinishedBlob(&builder1);
std::unique_ptr<BlobDataHandle> blob_data_handle2 =
- context_.AddFinishedBlob(&builder2);
+ context_->AddFinishedBlob(&builder2);
+
+ EXPECT_EQ(10u + 12u + 5u, context_->memory_controller().memory_usage());
ASSERT_TRUE(blob_data_handle);
ASSERT_TRUE(blob_data_handle2);
@@ -238,7 +403,9 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob) {
base::RunLoop().RunUntilIdle();
- blob_data_handle = context_.GetBlobDataFromUUID(kId1);
+ EXPECT_EQ(12u + 5u, context_->memory_controller().memory_usage());
+
+ blob_data_handle = context_->GetBlobDataFromUUID(kId1);
EXPECT_FALSE(blob_data_handle);
EXPECT_TRUE(blob_data_handle2);
data2 = blob_data_handle2->CreateSnapshot();
@@ -249,16 +416,19 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob) {
builder3.AppendBlob(kId2);
builder3.AppendBlob(kId2);
std::unique_ptr<BlobDataHandle> blob_data_handle3 =
- context_.AddFinishedBlob(&builder3);
+ context_->AddFinishedBlob(&builder3);
+ EXPECT_FALSE(blob_data_handle3->IsBeingBuilt());
blob_data_handle2.reset();
base::RunLoop().RunUntilIdle();
- blob_data_handle2 = context_.GetBlobDataFromUUID(kId2);
+ EXPECT_EQ(12u + 5u, context_->memory_controller().memory_usage());
+
+ blob_data_handle2 = context_->GetBlobDataFromUUID(kId2);
EXPECT_FALSE(blob_data_handle2);
EXPECT_TRUE(blob_data_handle3);
std::unique_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot();
- BlobDataBuilder canonicalized_blob_data3(kId3Prime);
+ BlobDataBuilder canonicalized_blob_data3(kId3);
canonicalized_blob_data3.AppendData("Data2");
canonicalized_blob_data3.AppendData(" is the best");
canonicalized_blob_data3.AppendData("Data2");
@@ -275,12 +445,11 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
// A value which does not fit in a 4-byte data type. Used to confirm that
// large values are supported on 32-bit Chromium builds. Regression test for:
// crbug.com/458122.
- const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max();
+ const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max() - 1;
const uint64_t kBlobLength = 5;
const std::string kId1("id1");
const std::string kId2("id2");
- base::MessageLoop fake_io_message_loop;
BlobDataBuilder builder1(kId1);
builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now());
@@ -289,9 +458,9 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength);
std::unique_ptr<BlobDataHandle> blob_data_handle1 =
- context_.AddFinishedBlob(&builder1);
+ context_->AddFinishedBlob(&builder1);
std::unique_ptr<BlobDataHandle> blob_data_handle2 =
- context_.AddFinishedBlob(&builder2);
+ context_->AddFinishedBlob(&builder2);
ASSERT_TRUE(blob_data_handle1);
ASSERT_TRUE(blob_data_handle2);
@@ -307,7 +476,6 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
}
TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) {
- base::MessageLoop fake_io_message_loop;
scoped_refptr<BlobDataBuilder::DataHandle>
data_handle = new EmptyDataHandle();
@@ -347,9 +515,6 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) {
const std::string kId1("id1");
const std::string kId2("id2");
const std::string kId3("id3");
- const std::string kId2Prime("id2.prime");
-
- base::MessageLoop fake_io_message_loop;
// Setup a set of blob data for testing.
base::Time time1, time2;
@@ -377,7 +542,7 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) {
blob_data3.AppendDiskCacheEntry(new EmptyDataHandle(), disk_cache_entry.get(),
kTestDiskCacheStreamIndex);
- BlobDataBuilder canonicalized_blob_data2(kId2Prime);
+ BlobDataBuilder canonicalized_blob_data2(kId2);
canonicalized_blob_data2.AppendData("Data3");
canonicalized_blob_data2.AppendData("a2___", 2);
canonicalized_blob_data2.AppendFile(
@@ -389,7 +554,7 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) {
std::unique_ptr<BlobDataHandle> blob_data_handle;
// Test a blob referring to only data and a file.
- blob_data_handle = context_.AddFinishedBlob(&blob_data1);
+ blob_data_handle = context_->AddFinishedBlob(&blob_data1);
ASSERT_TRUE(blob_data_handle);
std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
@@ -397,14 +562,14 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) {
EXPECT_EQ(*data, blob_data1);
// Test a blob composed in part with another blob.
- blob_data_handle = context_.AddFinishedBlob(&blob_data2);
+ blob_data_handle = context_->AddFinishedBlob(&blob_data2);
data = blob_data_handle->CreateSnapshot();
ASSERT_TRUE(blob_data_handle);
ASSERT_TRUE(data);
EXPECT_EQ(*data, canonicalized_blob_data2);
// Test a blob referring to only data and a disk cache entry.
- blob_data_handle = context_.AddFinishedBlob(&blob_data3);
+ blob_data_handle = context_->AddFinishedBlob(&blob_data3);
data = blob_data_handle->CreateSnapshot();
ASSERT_TRUE(blob_data_handle);
EXPECT_EQ(*data, blob_data3);
@@ -414,17 +579,15 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) {
}
TEST_F(BlobStorageContextTest, PublicBlobUrls) {
- base::MessageLoop fake_io_message_loop;
-
// Build up a basic blob.
const std::string kId("id");
std::unique_ptr<BlobDataHandle> first_handle = SetupBasicBlob(kId);
// Now register a url for that blob.
GURL kUrl("blob:id");
- context_.RegisterPublicBlobURL(kUrl, kId);
+ context_->RegisterPublicBlobURL(kUrl, kId);
std::unique_ptr<BlobDataHandle> blob_data_handle =
- context_.GetBlobDataFromPublicURL(kUrl);
+ context_->GetBlobDataFromPublicURL(kUrl);
ASSERT_TRUE(blob_data_handle.get());
EXPECT_EQ(kId, blob_data_handle->uuid());
std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
@@ -434,64 +597,62 @@ TEST_F(BlobStorageContextTest, PublicBlobUrls) {
// The url registration should keep the blob alive even after
// explicit references are dropped.
- blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl);
+ blob_data_handle = context_->GetBlobDataFromPublicURL(kUrl);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
- base::RunLoop().RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Finally get rid of the url registration and the blob.
- context_.RevokePublicBlobURL(kUrl);
- blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl);
+ context_->RevokePublicBlobURL(kUrl);
+ blob_data_handle = context_->GetBlobDataFromPublicURL(kUrl);
EXPECT_FALSE(blob_data_handle.get());
- EXPECT_FALSE(context_.registry().HasEntry(kId));
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
}
TEST_F(BlobStorageContextTest, TestUnknownBrokenAndBuildingBlobReference) {
- base::MessageLoop fake_io_message_loop;
const std::string kBrokenId("broken_id");
const std::string kBuildingId("building_id");
const std::string kReferencingId("referencing_id");
const std::string kUnknownId("unknown_id");
- // Create a broken blob and a building blob.
- context_.CreatePendingBlob(kBuildingId, "", "");
- context_.CreatePendingBlob(kBrokenId, "", "");
- context_.CancelPendingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN);
- EXPECT_TRUE(context_.IsBroken(kBrokenId));
- EXPECT_TRUE(context_.registry().HasEntry(kBrokenId));
+ // Create a broken blob.
+ std::unique_ptr<BlobDataHandle> broken_handle =
+ context_->AddBrokenBlob(kBrokenId, "", "", BlobStatus::ERR_OUT_OF_MEMORY);
+ EXPECT_TRUE(broken_handle->GetBlobStatus() == BlobStatus::ERR_OUT_OF_MEMORY);
+ EXPECT_TRUE(context_->registry().HasEntry(kBrokenId));
// Try to create a blob with a reference to an unknown blob.
BlobDataBuilder builder(kReferencingId);
builder.AppendData("data");
builder.AppendBlob(kUnknownId);
- std::unique_ptr<BlobDataHandle> handle = context_.AddFinishedBlob(builder);
+ std::unique_ptr<BlobDataHandle> handle = context_->AddFinishedBlob(builder);
EXPECT_TRUE(handle->IsBroken());
- EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_FALSE(context_->registry().HasEntry(kReferencingId));
// Try to create a blob with a reference to the broken blob.
BlobDataBuilder builder2(kReferencingId);
builder2.AppendData("data");
builder2.AppendBlob(kBrokenId);
- handle = context_.AddFinishedBlob(builder2);
+ handle = context_->AddFinishedBlob(builder2);
EXPECT_TRUE(handle->IsBroken());
- EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_FALSE(context_->registry().HasEntry(kReferencingId));
// Try to create a blob with a reference to the building blob.
BlobDataBuilder builder3(kReferencingId);
builder3.AppendData("data");
builder3.AppendBlob(kBuildingId);
- handle = context_.AddFinishedBlob(builder3);
+ handle = context_->AddFinishedBlob(builder3);
EXPECT_TRUE(handle->IsBroken());
- EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
+ EXPECT_FALSE(context_->registry().HasEntry(kReferencingId));
}
// TODO(michaeln): tests for the depcrecated url stuff
diff --git a/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc b/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
index 918554202b0..9cb2285f11f 100644
--- a/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
@@ -5,13 +5,12 @@
#include "storage/browser/blob/blob_storage_registry.h"
#include "base/callback.h"
+#include "storage/browser/blob/blob_entry.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace storage {
namespace {
-using Entry = BlobStorageRegistry::Entry;
-using BlobState = BlobStorageRegistry::BlobState;
TEST(BlobStorageRegistry, UUIDRegistration) {
const std::string kBlob1 = "Blob1";
@@ -22,14 +21,12 @@ TEST(BlobStorageRegistry, UUIDRegistration) {
EXPECT_FALSE(registry.DeleteEntry(kBlob1));
EXPECT_EQ(0u, registry.blob_count());
- Entry* entry = registry.CreateEntry(kBlob1, kType, kDisposition);
+ BlobEntry* entry = registry.CreateEntry(kBlob1, kType, kDisposition);
ASSERT_NE(nullptr, entry);
- EXPECT_EQ(BlobState::PENDING, entry->state);
- EXPECT_EQ(kType, entry->content_type);
- EXPECT_EQ(kDisposition, entry->content_disposition);
- EXPECT_EQ(1u, entry->refcount);
- EXPECT_FALSE(entry->data.get() || entry->data_builder.get());
- EXPECT_EQ(0u, entry->build_completion_callbacks.size());
+ EXPECT_EQ(BlobStatus::PENDING_QUOTA, entry->status());
+ EXPECT_EQ(kType, entry->content_type());
+ EXPECT_EQ(kDisposition, entry->content_disposition());
+ EXPECT_EQ(0u, entry->refcount());
EXPECT_EQ(entry, registry.GetEntry(kBlob1));
EXPECT_TRUE(registry.DeleteEntry(kBlob1));
@@ -52,7 +49,7 @@ TEST(BlobStorageRegistry, URLRegistration) {
EXPECT_FALSE(registry.DeleteURLMapping(kURL, nullptr));
EXPECT_FALSE(registry.CreateUrlMapping(kURL, kBlob));
EXPECT_EQ(0u, registry.url_count());
- Entry* entry = registry.CreateEntry(kBlob, kType, kDisposition);
+ BlobEntry* entry = registry.CreateEntry(kBlob, kType, kDisposition);
EXPECT_FALSE(registry.IsURLMapped(kURL));
EXPECT_TRUE(registry.CreateUrlMapping(kURL, kBlob));
diff --git a/chromium/content/browser/blob_storage/blob_transport_host_unittest.cc b/chromium/content/browser/blob_storage/blob_transport_host_unittest.cc
new file mode 100644
index 00000000000..55877d97fdd
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_transport_host_unittest.cc
@@ -0,0 +1,512 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_browser_thread_bundle.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"
+#include "storage/browser/blob/blob_transport_host.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+namespace {
+const std::string kBlobUUID = "blobUUIDYAY";
+const std::string kContentType = "content_type";
+const std::string kContentDisposition = "content_disposition";
+const std::string kCompletedBlobUUID = "completedBlob";
+const std::string kCompletedBlobData = "completedBlobData";
+
+const size_t kTestBlobStorageIPCThresholdBytes = 5;
+const size_t kTestBlobStorageMaxSharedMemoryBytes = 20;
+
+const size_t kTestBlobStorageMaxBlobMemorySize = 400;
+const uint64_t kTestBlobStorageMaxDiskSpace = 4000;
+const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
+const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+
+void PopulateBytes(char* bytes, size_t length) {
+ for (size_t i = 0; i < length; i++) {
+ bytes[i] = static_cast<char>(i);
+ }
+}
+
+void AddMemoryItem(size_t length, std::vector<DataElement>* out) {
+ DataElement bytes;
+ bytes.SetToBytesDescription(length);
+ out->push_back(bytes);
+}
+
+void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) {
+ DataElement bytes;
+ bytes.SetToAllocatedBytes(length);
+ PopulateBytes(bytes.mutable_bytes(), length);
+ out->push_back(bytes);
+}
+
+void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) {
+ DataElement bytes;
+ bytes.SetToAllocatedBytes(length);
+ PopulateBytes(bytes.mutable_bytes(), length);
+ out->AppendData(bytes.bytes(), length);
+}
+
+void AddBlobItem(std::vector<DataElement>* out) {
+ DataElement blob;
+ blob.SetToBlob(kCompletedBlobUUID);
+ out->push_back(blob);
+}
+} // namespace
+
+class BlobTransportHostTest : public testing::Test {
+ public:
+ BlobTransportHostTest()
+ : status_code_(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS),
+ request_called_(false) {}
+ ~BlobTransportHostTest() override {}
+
+ void SetUp() override {
+ status_code_ = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
+ request_called_ = false;
+ requests_.clear();
+ memory_handles_.clear();
+ storage::BlobStorageLimits limits;
+ limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes;
+ limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes;
+ limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize;
+ limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace;
+ limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes;
+ limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
+ context_.mutable_memory_controller()->set_limits_for_testing(limits);
+ BlobDataBuilder builder(kCompletedBlobUUID);
+ builder.AppendData(kCompletedBlobData);
+ completed_blob_handle_ = context_.AddFinishedBlob(builder);
+ EXPECT_EQ(BlobStatus::DONE, completed_blob_handle_->GetBlobStatus());
+ }
+
+ void StatusCallback(BlobStatus status) {
+ status_called_ = true;
+ status_code_ = status;
+ }
+
+ void RequestMemoryCallback(
+ std::vector<storage::BlobItemBytesRequest> requests,
+ std::vector<base::SharedMemoryHandle> shared_memory_handles,
+ std::vector<base::File> files) {
+ requests_ = std::move(requests);
+ memory_handles_ = std::move(shared_memory_handles);
+ request_called_ = true;
+ }
+
+ BlobStatus BuildBlobAsync(const std::string& uuid,
+ const std::vector<DataElement>& descriptions,
+ std::unique_ptr<BlobDataHandle>* storage) {
+ EXPECT_NE(storage, nullptr);
+ request_called_ = false;
+ status_called_ = false;
+ *storage = host_.StartBuildingBlob(
+ uuid, kContentType, kContentDisposition, descriptions, &context_,
+ base::Bind(&BlobTransportHostTest::RequestMemoryCallback,
+ base::Unretained(this)),
+ base::Bind(&BlobTransportHostTest::StatusCallback,
+ base::Unretained(this)));
+ if (status_called_)
+ return status_code_;
+ else
+ return context_.GetBlobStatus(uuid);
+ }
+
+ BlobStatus GetBlobStatus(const std::string& uuid) const {
+ return context_.GetBlobStatus(uuid);
+ }
+
+ bool IsBeingBuiltInContext(const std::string& uuid) const {
+ return BlobStatusIsPending(context_.GetBlobStatus(uuid));
+ }
+
+ content::TestBrowserThreadBundle browser_thread_bundle_;
+ BlobStorageContext context_;
+ BlobTransportHost host_;
+ bool status_called_;
+ BlobStatus status_code_;
+
+ bool request_called_;
+ std::vector<storage::BlobItemBytesRequest> requests_;
+ std::vector<base::SharedMemoryHandle> memory_handles_;
+ std::unique_ptr<BlobDataHandle> completed_blob_handle_;
+};
+
+// The 'shortcut' method is when the data is included in the initial IPCs and
+// the browser uses that instead of requesting the memory.
+TEST_F(BlobTransportHostTest, TestShortcut) {
+ std::vector<DataElement> descriptions;
+
+ AddShortcutMemoryItem(10, &descriptions);
+ AddBlobItem(&descriptions);
+ AddShortcutMemoryItem(300, &descriptions);
+
+ BlobDataBuilder expected(kBlobUUID);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
+ AddShortcutMemoryItem(10, &expected);
+ expected.AppendData(kCompletedBlobData);
+ AddShortcutMemoryItem(300, &expected);
+
+ std::unique_ptr<BlobDataHandle> handle;
+ EXPECT_EQ(BlobStatus::DONE, BuildBlobAsync(kBlobUUID, descriptions, &handle));
+
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+ EXPECT_FALSE(handle->IsBeingBuilt());
+ ASSERT_FALSE(handle->IsBroken());
+ std::unique_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
+ EXPECT_EQ(expected, *data);
+ data.reset();
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobTransportHostTest, TestShortcutNoRoom) {
+ std::vector<DataElement> descriptions;
+
+ AddShortcutMemoryItem(10, &descriptions);
+ AddBlobItem(&descriptions);
+ AddShortcutMemoryItem(5000, &descriptions);
+
+ std::unique_ptr<BlobDataHandle> handle;
+ EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle));
+
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+};
+
+TEST_F(BlobTransportHostTest, TestSingleSharedMemRequest) {
+ std::vector<DataElement> descriptions;
+ const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
+ AddMemoryItem(kSize, &descriptions);
+
+ std::unique_ptr<BlobDataHandle> handle;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle));
+ EXPECT_TRUE(handle);
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, handle->GetBlobStatus());
+
+ EXPECT_TRUE(request_called_);
+ EXPECT_EQ(1u, host_.blob_building_count());
+ ASSERT_EQ(1u, requests_.size());
+ request_called_ = false;
+
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0),
+ requests_.at(0));
+};
+
+TEST_F(BlobTransportHostTest, TestMultipleSharedMemRequests) {
+ std::vector<DataElement> descriptions;
+ const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1;
+ const char kFirstBlockByte = 7;
+ const char kSecondBlockByte = 19;
+ AddMemoryItem(kSize, &descriptions);
+
+ BlobDataBuilder expected(kBlobUUID);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
+ char data[kSize];
+ memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
+ expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
+ expected.AppendData(&kSecondBlockByte, 1);
+
+ std::unique_ptr<BlobDataHandle> handle;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle));
+
+ EXPECT_TRUE(request_called_);
+ EXPECT_EQ(1u, host_.blob_building_count());
+ ASSERT_EQ(1u, requests_.size());
+ request_called_ = false;
+
+ // We need to grab a duplicate handle so we can have two blocks open at the
+ // same time.
+ base::SharedMemoryHandle shared_mem_handle =
+ base::SharedMemory::DuplicateHandle(memory_handles_.at(0));
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(shared_mem_handle));
+ base::SharedMemory shared_memory(shared_mem_handle, false);
+ EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes));
+
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
+ 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0),
+ requests_.at(0));
+
+ memset(shared_memory.memory(), kFirstBlockByte,
+ kTestBlobStorageMaxSharedMemoryBytes);
+
+ BlobItemBytesResponse response(0);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, GetBlobStatus(kBlobUUID));
+ ASSERT_TRUE(handle);
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, handle->GetBlobStatus());
+
+ EXPECT_TRUE(request_called_);
+ EXPECT_EQ(1u, host_.blob_building_count());
+ ASSERT_EQ(1u, requests_.size());
+ request_called_ = false;
+
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(
+ 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0),
+ requests_.at(0));
+
+ memset(shared_memory.memory(), kSecondBlockByte, 1);
+
+ response.request_number = 1;
+ responses[0] = response;
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_TRUE(handle);
+ EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+ std::unique_ptr<BlobDataHandle> blob_handle =
+ context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle->IsBroken());
+ std::unique_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
+};
+
+TEST_F(BlobTransportHostTest, TestBasicIPCAndStopBuilding) {
+ std::vector<DataElement> descriptions;
+
+ AddMemoryItem(2, &descriptions);
+ AddBlobItem(&descriptions);
+ AddMemoryItem(2, &descriptions);
+
+ BlobDataBuilder expected(kBlobUUID);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
+ AddShortcutMemoryItem(2, &expected);
+ expected.AppendData(kCompletedBlobData);
+ AddShortcutMemoryItem(2, &expected);
+
+ std::unique_ptr<BlobDataHandle> handle1;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle1));
+ EXPECT_TRUE(handle1);
+ host_.CancelBuildingBlob(kBlobUUID, BlobStatus::ERR_OUT_OF_MEMORY, &context_);
+
+ // Check that we're broken, and then remove the blob.
+ EXPECT_FALSE(handle1->IsBeingBuilt());
+ EXPECT_TRUE(handle1->IsBroken());
+ handle1.reset();
+ base::RunLoop().RunUntilIdle();
+ handle1 = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(handle1.get());
+
+ // This should succeed because we've removed all references to the blob.
+ std::unique_ptr<BlobDataHandle> handle2;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle2));
+
+ EXPECT_TRUE(request_called_);
+ EXPECT_EQ(1u, host_.blob_building_count());
+ request_called_ = false;
+
+ BlobItemBytesResponse response1(0);
+ PopulateBytes(response1.allocate_mutable_data(2), 2);
+ BlobItemBytesResponse response2(1);
+ PopulateBytes(response2.allocate_mutable_data(2), 2);
+ std::vector<BlobItemBytesResponse> responses = {response1, response2};
+
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_EQ(BlobStatus::DONE, handle2->GetBlobStatus());
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+ EXPECT_FALSE(handle2->IsBeingBuilt());
+ EXPECT_FALSE(handle2->IsBroken());
+ std::unique_ptr<BlobDataSnapshot> blob_data = handle2->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
+};
+
+TEST_F(BlobTransportHostTest, TestBreakingAllBuilding) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ std::vector<DataElement> descriptions;
+ AddMemoryItem(2, &descriptions);
+
+ // Register blobs.
+ std::unique_ptr<BlobDataHandle> handle1;
+ std::unique_ptr<BlobDataHandle> handle2;
+ std::unique_ptr<BlobDataHandle> handle3;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob1, descriptions, &handle1));
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob2, descriptions, &handle2));
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob3, descriptions, &handle3));
+
+ EXPECT_TRUE(request_called_);
+ EXPECT_TRUE(handle1->IsBeingBuilt() && handle2->IsBeingBuilt() &&
+ handle3->IsBeingBuilt());
+ EXPECT_FALSE(handle1->IsBroken() || handle2->IsBroken() ||
+ handle3->IsBroken());
+
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob1) && IsBeingBuiltInContext(kBlob2) &&
+ IsBeingBuiltInContext(kBlob3));
+
+ // This shouldn't call the transport complete callbacks, so our handles should
+ // still be false.
+ host_.CancelAll(&context_);
+
+ EXPECT_FALSE(handle1->IsBeingBuilt() || handle2->IsBeingBuilt() ||
+ handle3->IsBeingBuilt());
+ EXPECT_TRUE(handle1->IsBroken() && handle2->IsBroken() &&
+ handle3->IsBroken());
+
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobTransportHostTest, TestBadIPCs) {
+ std::vector<DataElement> descriptions;
+
+ // Test reusing same blob uuid.
+ AddMemoryItem(10, &descriptions);
+ AddBlobItem(&descriptions);
+ AddMemoryItem(300, &descriptions);
+ std::unique_ptr<BlobDataHandle> handle1;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle1));
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlobUUID));
+ EXPECT_TRUE(request_called_);
+ host_.CancelBuildingBlob(kBlobUUID, BlobStatus::ERR_REFERENCED_BLOB_BROKEN,
+ &context_);
+ handle1.reset();
+ EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
+
+ // Test empty responses.
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle1));
+ std::vector<BlobItemBytesResponse> responses;
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
+ handle1->GetBlobStatus());
+ handle1.reset();
+
+ // Test response problems below here.
+ descriptions.clear();
+ AddMemoryItem(2, &descriptions);
+ AddBlobItem(&descriptions);
+ AddMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle1));
+
+ // Invalid request number.
+ BlobItemBytesResponse response1(3);
+ PopulateBytes(response1.allocate_mutable_data(2), 2);
+ responses = {response1};
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
+ handle1->GetBlobStatus());
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ handle1.reset();
+ base::RunLoop().RunUntilIdle();
+
+ // Duplicate request number responses.
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlobUUID, descriptions, &handle1));
+ response1.request_number = 0;
+ BlobItemBytesResponse response2(0);
+ PopulateBytes(response2.allocate_mutable_data(2), 2);
+ responses = {response1, response2};
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_);
+ EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
+ handle1->GetBlobStatus());
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ handle1.reset();
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobTransportHostTest, WaitOnReferencedBlob) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ std::vector<DataElement> descriptions;
+ AddMemoryItem(2, &descriptions);
+
+ // Register blobs.
+ std::unique_ptr<BlobDataHandle> handle1;
+
+ std::unique_ptr<BlobDataHandle> handle2;
+ std::unique_ptr<BlobDataHandle> handle3;
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob1, descriptions, &handle1));
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob2, descriptions, &handle2));
+ EXPECT_TRUE(request_called_);
+ request_called_ = false;
+
+ // Finish the third one, with a reference to the first and second blob.
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ element.SetToBlob(kBlob2);
+ descriptions.push_back(element);
+
+ EXPECT_EQ(BlobStatus::PENDING_TRANSPORT,
+ BuildBlobAsync(kBlob3, descriptions, &handle3));
+ EXPECT_TRUE(request_called_);
+ request_called_ = false;
+
+ // Finish the third, but we should still be 'building' it.
+ BlobItemBytesResponse response1(0);
+ PopulateBytes(response1.allocate_mutable_data(2), 2);
+ std::vector<BlobItemBytesResponse> responses = {response1};
+ host_.OnMemoryResponses(kBlob3, responses, &context_);
+ EXPECT_EQ(BlobStatus::PENDING_INTERNALS, handle3->GetBlobStatus());
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the first.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ host_.OnMemoryResponses(kBlob1, responses, &context_);
+ EXPECT_EQ(BlobStatus::DONE, handle1->GetBlobStatus());
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Verify we're not done.
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the second.
+ host_.OnMemoryResponses(kBlob2, responses, &context_);
+ EXPECT_EQ(BlobStatus::DONE, handle2->GetBlobStatus());
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Finally, we should be finished with third blob.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
+};
+
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc b/chromium/content/browser/blob_storage/blob_transport_request_builder_unittest.cc
index 071a06bb23f..71e0956113f 100644
--- a/chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_transport_request_builder_unittest.cc
@@ -8,15 +8,13 @@
#include <string>
#include "base/logging.h"
-#include "storage/browser/blob/blob_async_transport_request_builder.h"
+#include "storage/browser/blob/blob_transport_request_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage {
namespace {
const char kNewUUID[] = "newUUID";
-const base::FilePath kFuturePopulatingFilePath = base::FilePath::FromUTF8Unsafe(
- std::string(BlobDataBuilder::kAppendFutureFileTemporaryFileName));
const char kFakeBlobUUID[] = "fakeBlob";
void AddMemoryItem(size_t length, std::vector<DataElement>* out) {
@@ -41,7 +39,7 @@ void AddBlobItem(std::vector<DataElement>* out) {
}
TEST(BlobAsyncTransportRequestBuilderTest, TestNoMemoryItems) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -65,7 +63,7 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestNoMemoryItems) {
}
TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFile) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -87,13 +85,12 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFile) {
memory_item_request.message);
BlobDataBuilder expected_builder(kNewUUID);
- expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 305,
- base::Time::FromDoubleT(0));
+ expected_builder.AppendFutureFile(0, 305, 0);
EXPECT_EQ(expected_builder, builder);
}
TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFiles) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -131,18 +128,15 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFiles) {
memory_item_request.message);
BlobDataBuilder expected_builder(kNewUUID);
- expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
- base::Time::FromDoubleT(0));
- expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
- base::Time::FromDoubleT(0));
- expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 200,
- base::Time::FromDoubleT(0));
+ expected_builder.AppendFutureFile(0, 400, 0);
+ expected_builder.AppendFutureFile(0, 400, 1);
+ expected_builder.AppendFutureFile(0, 200, 2);
EXPECT_EQ(expected_builder, builder);
}
TEST(BlobAsyncTransportRequestBuilderTest,
TestLargeBlocksConsolidatingInFiles) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -189,7 +183,7 @@ TEST(BlobAsyncTransportRequestBuilderTest,
}
TEST(BlobAsyncTransportRequestBuilderTest, TestSharedMemorySegmentation) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -237,7 +231,7 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestSharedMemorySegmentation) {
TEST(BlobAsyncTransportRequestBuilderTest,
TestSharedMemorySegmentationAndStorage) {
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
std::vector<DataElement> infos;
@@ -295,7 +289,7 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestSimpleIPC) {
// Test simple IPC strategy, where size < max_ipc_memory_size and we have
// just one item.
std::vector<DataElement> infos;
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
AddMemoryItem(10, &infos);
AddBlobItem(&infos);
@@ -318,7 +312,7 @@ TEST(BlobAsyncTransportRequestBuilderTest, TestSimpleIPC) {
TEST(BlobAsyncTransportRequestBuilderTest, TestMultipleIPC) {
// Same as above, but with 2 items and a blob in-between.
std::vector<DataElement> infos;
- BlobAsyncTransportRequestBuilder strategy;
+ BlobTransportRequestBuilder strategy;
BlobDataBuilder builder(kNewUUID);
AddShortcutMemoryItem(10, &infos); // should have no behavior change
AddBlobItem(&infos);
diff --git a/chromium/content/browser/blob_storage/blob_url_browsertest.cc b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
index f25ee5b258f..db20d8e2268 100644
--- a/chromium/content/browser/blob_storage/blob_url_browsertest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
@@ -26,8 +26,8 @@ class BlobUrlBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
private:
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
index a340edcc084..767ea23886e 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -11,7 +11,7 @@
#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "content/browser/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "content/common/bluetooth/web_bluetooth_device_id.h"
using device::BluetoothUUID;
@@ -115,11 +115,27 @@ const std::string& BluetoothAllowedDevicesMap::GetDeviceAddress(
: id_iter->second;
}
+bool BluetoothAllowedDevicesMap::IsOriginAllowedToAccessAtLeastOneService(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id) const {
+ auto id_map_iter = origin_to_device_id_to_services_map_.find(origin);
+ if (id_map_iter == origin_to_device_id_to_services_map_.end()) {
+ return false;
+ }
+
+ const auto& device_id_to_services_map = id_map_iter->second;
+
+ auto id_iter = device_id_to_services_map.find(device_id);
+
+ return id_iter == device_id_to_services_map.end() ? false
+ : !id_iter->second.empty();
+}
+
bool BluetoothAllowedDevicesMap::IsOriginAllowedToAccessService(
const url::Origin& origin,
const WebBluetoothDeviceId& device_id,
const BluetoothUUID& service_uuid) const {
- if (BluetoothBlacklist::Get().IsExcluded(service_uuid)) {
+ if (BluetoothBlocklist::Get().IsExcluded(service_uuid)) {
return false;
}
@@ -150,13 +166,20 @@ void BluetoothAllowedDevicesMap::AddUnionOfServicesTo(
const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options,
std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash>*
unionOfServices) {
- for (const auto& filter : options->filters) {
- for (const base::Optional<BluetoothUUID>& uuid : filter->services) {
- unionOfServices->insert(uuid.value());
+ if (options->filters) {
+ for (const auto& filter : options->filters.value()) {
+ if (!filter->services) {
+ continue;
+ }
+
+ for (const BluetoothUUID& uuid : filter->services.value()) {
+ unionOfServices->insert(uuid);
+ }
}
}
- for (const base::Optional<BluetoothUUID>& uuid : options->optional_services) {
- unionOfServices->insert(uuid.value());
+
+ for (const BluetoothUUID& uuid : options->optional_services) {
+ unionOfServices->insert(uuid);
}
}
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
index 86dadd2143d..3dd20114456 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
@@ -23,8 +23,6 @@ class BluetoothUUID;
namespace content {
-struct BluetoothScanFilter;
-
// Keeps track of which origins are allowed to access which devices and
// their services.
//
@@ -59,6 +57,12 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
const std::string& GetDeviceAddress(const url::Origin& origin,
const WebBluetoothDeviceId& device_id);
+ // Returns true if the origin has previously been granted access to at least
+ // one service.
+ bool IsOriginAllowedToAccessAtLeastOneService(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id) const;
+
// Returns true if the origin has previously been granted access to
// the service.
bool IsOriginAllowedToAccessService(
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
index 1c4b18ebbcd..c5e463278e6 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
@@ -19,6 +19,8 @@ const url::Origin kTestOrigin2(GURL("https://www.example2.com"));
const std::string kDeviceAddress1 = "00:00:00";
const std::string kDeviceAddress2 = "11:11:11";
+const std::string kDeviceName = "TestName";
+
const char kGlucoseUUIDString[] = "00001808-0000-1000-8000-00805f9b34fb";
const char kHeartRateUUIDString[] = "0000180d-0000-1000-8000-00805f9b34fb";
const char kBatteryServiceUUIDString[] = "0000180f-0000-1000-8000-00805f9b34fb";
@@ -179,22 +181,49 @@ TEST_F(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id));
}
+TEST_F(BluetoothAllowedDevicesMapTest, NoPermissionForAnyService) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ // Setup device.
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scan_filter->name = kDeviceName;
+ options->filters.emplace();
+ options->filters->push_back({scan_filter.Clone()});
+
+ // Add to map.
+ const WebBluetoothDeviceId device_id =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options);
+
+ // Try to access at least one service.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id, kGlucoseUUID));
+}
+
TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
BluetoothAllowedDevicesMap allowed_devices_map;
// Setup device.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter1 =
blink::mojom::WebBluetoothScanFilter::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter2 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter1->services.push_back(kGlucoseUUID);
- options->filters.push_back(scanFilter1.Clone());
+ scan_filter1->services.emplace();
+ scan_filter1->services->push_back(kGlucoseUUID);
+ options->filters.emplace();
+ options->filters->push_back(scan_filter1.Clone());
- scanFilter2->services.push_back(kHeartRateUUID);
- options->filters.push_back(scanFilter2.Clone());
+ scan_filter2->services.emplace();
+ scan_filter2->services->push_back(kHeartRateUUID);
+ options->filters->push_back(scan_filter2.Clone());
options->optional_services.push_back(kBatteryServiceUUID);
options->optional_services.push_back(kHeartRateUUID);
@@ -204,6 +233,8 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options);
// Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id1));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -218,6 +249,8 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
// Try to access allowed services after removing device.
allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id1));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -229,13 +262,16 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- options2->filters.push_back(scanFilter1.Clone());
- options2->filters.push_back(scanFilter2.Clone());
+ options2->filters.emplace();
+ options2->filters->push_back(scan_filter1.Clone());
+ options2->filters->push_back(scan_filter2.Clone());
const WebBluetoothDeviceId device_id2 =
allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options2);
// Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id2));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id2, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -260,22 +296,26 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginTwoDevices) {
// Setup request for device #1.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter1 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter1->services.push_back(kGlucoseUUID);
- options1->filters.push_back(std::move(scanFilter1));
+ scan_filter1->services.emplace();
+ scan_filter1->services->push_back(kGlucoseUUID);
+ options1->filters.emplace();
+ options1->filters->push_back(std::move(scan_filter1));
options1->optional_services.push_back(kHeartRateUUID);
// Setup request for device #2.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter2 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter2->services.push_back(kBatteryServiceUUID);
- options2->filters.push_back(std::move(scanFilter2));
+ scan_filter2->services.emplace();
+ scan_filter2->services->push_back(kBatteryServiceUUID);
+ options2->filters.emplace();
+ options2->filters->push_back(std::move(scan_filter2));
options2->optional_services.push_back(kBloodPressureUUID);
@@ -286,11 +326,15 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginTwoDevices) {
allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress2, options2);
// Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id1));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kHeartRateUUID));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id2));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id2, kBatteryServiceUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -317,22 +361,26 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
// Setup request #1 for device.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter1 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter1->services.push_back(kGlucoseUUID);
- options1->filters.push_back(std::move(scanFilter1));
+ scan_filter1->services.emplace();
+ scan_filter1->services->push_back(kGlucoseUUID);
+ options1->filters.emplace();
+ options1->filters->push_back(std::move(scan_filter1));
options1->optional_services.push_back(kHeartRateUUID);
// Setup request #2 for device.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter2 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter2->services.push_back(kBatteryServiceUUID);
- options2->filters.push_back(std::move(scanFilter2));
+ scan_filter2->services.emplace();
+ scan_filter2->services->push_back(kBatteryServiceUUID);
+ options2->filters.emplace();
+ options2->filters->push_back(std::move(scan_filter2));
options2->optional_services.push_back(kBloodPressureUUID);
@@ -343,11 +391,15 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
allowed_devices_map.AddDevice(kTestOrigin2, kDeviceAddress1, options2);
// Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id1));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kHeartRateUUID));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin2, device_id2));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin2, device_id2, kBatteryServiceUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -359,6 +411,8 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kBloodPressureUUID));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id2));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id2, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -373,6 +427,8 @@ TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin2, device_id2, kHeartRateUUID));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin2, device_id1));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin2, device_id1, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -389,11 +445,13 @@ TEST_F(BluetoothAllowedDevicesMapTest, MergeServices) {
// Setup first request.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter1 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter1->services.push_back(kGlucoseUUID);
- options1->filters.push_back(std::move(scanFilter1));
+ scan_filter1->services.emplace();
+ scan_filter1->services->push_back(kGlucoseUUID);
+ options1->filters.emplace();
+ options1->filters->push_back(std::move(scan_filter1));
options1->optional_services.push_back(kBatteryServiceUUID);
@@ -404,11 +462,13 @@ TEST_F(BluetoothAllowedDevicesMapTest, MergeServices) {
// Setup second request.
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
blink::mojom::WebBluetoothRequestDeviceOptions::New();
- blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter2 =
blink::mojom::WebBluetoothScanFilter::New();
- scanFilter2->services.push_back(kHeartRateUUID);
- options2->filters.push_back(std::move(scanFilter2));
+ scan_filter2->services.emplace();
+ scan_filter2->services->push_back(kHeartRateUUID);
+ options2->filters.emplace();
+ options2->filters->push_back(std::move(scan_filter2));
options2->optional_services.push_back(kBloodPressureUUID);
@@ -418,6 +478,8 @@ TEST_F(BluetoothAllowedDevicesMapTest, MergeServices) {
EXPECT_EQ(device_id1, device_id2);
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id1));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
@@ -437,4 +499,24 @@ TEST_F(BluetoothAllowedDevicesMapTest, CorrectIdFormat) {
EXPECT_TRUE(WebBluetoothDeviceId::IsValid(device_id.str()));
}
+TEST_F(BluetoothAllowedDevicesMapTest, NoFilterServices) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ // Setup request.
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scan_filter =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ options->filters.emplace();
+ options->filters->push_back(std::move(scan_filter));
+
+ // Add to map.
+ const WebBluetoothDeviceId device_id =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options);
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessAtLeastOneService(
+ kTestOrigin1, device_id));
+}
+
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.cc b/chromium/content/browser/bluetooth/bluetooth_blocklist.cc
index a3c551e0334..4ba1dc13962 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_blocklist.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/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -14,11 +14,11 @@ using device::BluetoothUUID;
namespace {
-static base::LazyInstance<content::BluetoothBlacklist>::Leaky g_singleton =
+static base::LazyInstance<content::BluetoothBlocklist>::Leaky g_singleton =
LAZY_INSTANCE_INITIALIZER;
void RecordUMAParsedNonEmptyString(bool success) {
- UMA_HISTOGRAM_BOOLEAN("Bluetooth.Web.Blacklist.ParsedNonEmptyString",
+ UMA_HISTOGRAM_BOOLEAN("Bluetooth.Web.Blocklist.ParsedNonEmptyString",
success);
}
@@ -26,16 +26,16 @@ void RecordUMAParsedNonEmptyString(bool success) {
namespace content {
-BluetoothBlacklist::~BluetoothBlacklist() {}
+BluetoothBlocklist::~BluetoothBlocklist() {}
// static
-BluetoothBlacklist& BluetoothBlacklist::Get() {
+BluetoothBlocklist& BluetoothBlocklist::Get() {
return g_singleton.Get();
}
-void BluetoothBlacklist::Add(const BluetoothUUID& uuid, Value value) {
+void BluetoothBlocklist::Add(const BluetoothUUID& uuid, Value value) {
CHECK(uuid.IsValid());
- auto insert_result = blacklisted_uuids_.insert(std::make_pair(uuid, value));
+ auto insert_result = blocklisted_uuids_.insert(std::make_pair(uuid, value));
bool inserted = insert_result.second;
if (!inserted) {
Value& stored = insert_result.first->second;
@@ -44,13 +44,13 @@ void BluetoothBlacklist::Add(const BluetoothUUID& uuid, Value value) {
}
}
-void BluetoothBlacklist::Add(base::StringPiece blacklist_string) {
- if (blacklist_string.empty())
+void BluetoothBlocklist::Add(base::StringPiece blocklist_string) {
+ if (blocklist_string.empty())
return;
base::StringPairs kv_pairs;
bool parsed_values = false;
bool invalid_values = false;
- SplitStringIntoKeyValuePairs(blacklist_string,
+ SplitStringIntoKeyValuePairs(blocklist_string,
':', // Key-value delimiter
',', // Key-value pair delimiter
&kv_pairs);
@@ -77,19 +77,22 @@ void BluetoothBlacklist::Add(base::StringPiece blacklist_string) {
RecordUMAParsedNonEmptyString(parsed_values && !invalid_values);
}
-bool BluetoothBlacklist::IsExcluded(const BluetoothUUID& uuid) const {
+bool BluetoothBlocklist::IsExcluded(const BluetoothUUID& uuid) const {
CHECK(uuid.IsValid());
- const auto& it = blacklisted_uuids_.find(uuid);
- if (it == blacklisted_uuids_.end())
+ const auto& it = blocklisted_uuids_.find(uuid);
+ if (it == blocklisted_uuids_.end())
return false;
return it->second == Value::EXCLUDE;
}
-bool BluetoothBlacklist::IsExcluded(
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+bool BluetoothBlocklist::IsExcluded(
+ const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
for (const blink::mojom::WebBluetoothScanFilterPtr& filter : filters) {
- for (const base::Optional<BluetoothUUID>& service : filter->services) {
- if (IsExcluded(service.value())) {
+ if (!filter->services) {
+ continue;
+ }
+ for (const BluetoothUUID& service : filter->services.value()) {
+ if (IsExcluded(service)) {
return true;
}
}
@@ -97,65 +100,64 @@ bool BluetoothBlacklist::IsExcluded(
return false;
}
-bool BluetoothBlacklist::IsExcludedFromReads(const BluetoothUUID& uuid) const {
+bool BluetoothBlocklist::IsExcludedFromReads(const BluetoothUUID& uuid) const {
CHECK(uuid.IsValid());
- const auto& it = blacklisted_uuids_.find(uuid);
- if (it == blacklisted_uuids_.end())
+ const auto& it = blocklisted_uuids_.find(uuid);
+ if (it == blocklisted_uuids_.end())
return false;
return it->second == Value::EXCLUDE || it->second == Value::EXCLUDE_READS;
}
-bool BluetoothBlacklist::IsExcludedFromWrites(const BluetoothUUID& uuid) const {
+bool BluetoothBlocklist::IsExcludedFromWrites(const BluetoothUUID& uuid) const {
CHECK(uuid.IsValid());
- const auto& it = blacklisted_uuids_.find(uuid);
- if (it == blacklisted_uuids_.end())
+ const auto& it = blocklisted_uuids_.find(uuid);
+ if (it == blocklisted_uuids_.end())
return false;
return it->second == Value::EXCLUDE || it->second == Value::EXCLUDE_WRITES;
}
-void BluetoothBlacklist::RemoveExcludedUUIDs(
+void BluetoothBlocklist::RemoveExcludedUUIDs(
blink::mojom::WebBluetoothRequestDeviceOptions* options) {
- mojo::Array<base::Optional<BluetoothUUID>>
- optional_services_blacklist_filtered;
- for (const base::Optional<BluetoothUUID>& uuid : options->optional_services) {
- if (!IsExcluded(uuid.value())) {
- optional_services_blacklist_filtered.push_back(uuid);
+ std::vector<device::BluetoothUUID> optional_services_blocklist_filtered;
+ for (const BluetoothUUID& uuid : options->optional_services) {
+ if (!IsExcluded(uuid)) {
+ optional_services_blocklist_filtered.push_back(uuid);
}
}
- options->optional_services = std::move(optional_services_blacklist_filtered);
+ options->optional_services = std::move(optional_services_blocklist_filtered);
}
-void BluetoothBlacklist::ResetToDefaultValuesForTest() {
- blacklisted_uuids_.clear();
+void BluetoothBlocklist::ResetToDefaultValuesForTest() {
+ blocklisted_uuids_.clear();
PopulateWithDefaultValues();
PopulateWithServerProvidedValues();
}
-BluetoothBlacklist::BluetoothBlacklist() {
+BluetoothBlocklist::BluetoothBlocklist() {
PopulateWithDefaultValues();
PopulateWithServerProvidedValues();
}
-void BluetoothBlacklist::PopulateWithDefaultValues() {
- blacklisted_uuids_.clear();
+void BluetoothBlocklist::PopulateWithDefaultValues() {
+ blocklisted_uuids_.clear();
// Testing from Layout Tests Note:
//
// Random UUIDs for object & exclude permutations that do not exist in the
- // standard blacklist are included to facilitate integration testing from
- // Layout Tests. Unit tests can dynamically modify the blacklist, but don't
+ // standard blocklist are included to facilitate integration testing from
+ // Layout Tests. Unit tests can dynamically modify the blocklist, but don't
// offer the full integration test to the Web Bluetooth Javascript bindings.
//
// This is done for simplicity as opposed to exposing a testing API that can
- // add to the blacklist over time, which would be over engineered.
+ // add to the blocklist over time, which would be over engineered.
//
- // Remove testing UUIDs if the specified blacklist is updated to include UUIDs
+ // Remove testing UUIDs if the specified blocklist is updated to include UUIDs
// that match the specific permutations.
DCHECK(BluetoothUUID("00001800-0000-1000-8000-00805f9b34fb") ==
BluetoothUUID("1800"));
- // Blacklist UUIDs updated 2016-09-01 from:
- // https://github.com/WebBluetoothCG/registries/blob/master/gatt_blacklist.txt
+ // Blocklist UUIDs updated 2016-09-01 from:
+ // https://github.com/WebBluetoothCG/registries/blob/master/gatt_blocklist.txt
// Short UUIDs are used for readability of this list.
//
// Services:
@@ -180,10 +182,10 @@ void BluetoothBlacklist::PopulateWithDefaultValues() {
Value::EXCLUDE_READS);
}
-void BluetoothBlacklist::PopulateWithServerProvidedValues() {
+void BluetoothBlocklist::PopulateWithServerProvidedValues() {
// DCHECK to maybe help debug https://crbug.com/604078.
DCHECK(GetContentClient());
- Add(GetContentClient()->browser()->GetWebBluetoothBlacklist());
+ Add(GetContentClient()->browser()->GetWebBluetoothBlocklist());
}
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.h b/chromium/content/browser/bluetooth/bluetooth_blocklist.h
index ebc01dafe63..78e3b8a27b2 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist.h
+++ b/chromium/content/browser/bluetooth/bluetooth_blocklist.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_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
-#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
+#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_
#include <map>
#include <vector>
@@ -17,30 +17,30 @@
namespace content {
-// Implements the Web Bluetooth Blacklist policy as defined in the Web Bluetooth
+// Implements the Web Bluetooth Blocklist policy as defined in the Web Bluetooth
// specification:
-// https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blacklist
+// https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blocklist
//
// Client code may query UUIDs to determine if they are excluded from use by the
-// blacklist.
+// blocklist.
//
-// Singleton access via Get() enforces only one copy of blacklist.
-class CONTENT_EXPORT BluetoothBlacklist final {
+// Singleton access via Get() enforces only one copy of blocklist.
+class CONTENT_EXPORT BluetoothBlocklist final {
public:
- // Blacklist value terminology from Web Bluetooth specification:
- // https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blacklist
+ // Blocklist value terminology from Web Bluetooth specification:
+ // https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blocklist
enum class Value {
EXCLUDE, // Implies EXCLUDE_READS and EXCLUDE_WRITES.
EXCLUDE_READS, // Excluded from read operations.
EXCLUDE_WRITES // Excluded from write operations.
};
- ~BluetoothBlacklist();
+ ~BluetoothBlocklist();
- // Returns a singleton instance of the blacklist.
- static BluetoothBlacklist& Get();
+ // Returns a singleton instance of the blocklist.
+ static BluetoothBlocklist& Get();
- // Adds a UUID to the blacklist to be excluded from operations, merging with
+ // Adds a UUID to the blocklist to be excluded from operations, merging with
// any previous value and resulting in the strictest exclusion rule from the
// combination of the two, E.G.:
// Add(uuid, EXCLUDE_READS);
@@ -49,15 +49,15 @@ class CONTENT_EXPORT BluetoothBlacklist final {
// Requires UUID to be valid.
void Add(const device::BluetoothUUID&, Value);
- // Adds UUIDs to the blacklist by parsing a blacklist string and calling
+ // Adds UUIDs to the blocklist by parsing a blocklist string and calling
// Add(uuid, value).
//
- // The blacklist string format is defined at
- // ContentBrowserClient::GetWebBluetoothBlacklist().
+ // The blocklist string format is defined at
+ // ContentBrowserClient::GetWebBluetoothBlocklist().
//
// Malformed pairs in the string are ignored, including invalid UUID or
// exclusion values. Duplicate UUIDs follow Add()'s merging rule.
- void Add(base::StringPiece blacklist_string);
+ void Add(base::StringPiece blocklist_string);
// Returns if a UUID is excluded from all operations. UUID must be valid.
bool IsExcluded(const device::BluetoothUUID&) const;
@@ -65,7 +65,7 @@ class CONTENT_EXPORT BluetoothBlacklist final {
// Returns if any UUID in a set of filters is excluded from all operations.
// UUID must be valid.
bool IsExcluded(
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters);
+ const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters);
// Returns if a UUID is excluded from read operations. UUID must be valid.
bool IsExcludedFromReads(const device::BluetoothUUID&) const;
@@ -78,29 +78,29 @@ class CONTENT_EXPORT BluetoothBlacklist final {
void RemoveExcludedUUIDs(
blink::mojom::WebBluetoothRequestDeviceOptions* options);
- // Size of blacklist.
- size_t size() { return blacklisted_uuids_.size(); }
+ // Size of blocklist.
+ size_t size() { return blocklisted_uuids_.size(); }
void ResetToDefaultValuesForTest();
private:
// friend LazyInstance to permit access to private constructor.
- friend base::DefaultLazyInstanceTraits<BluetoothBlacklist>;
+ friend base::DefaultLazyInstanceTraits<BluetoothBlocklist>;
- BluetoothBlacklist();
+ BluetoothBlocklist();
void PopulateWithDefaultValues();
- // Populates blacklist with values obtained dynamically from a server, able
+ // Populates blocklist with values obtained dynamically from a server, able
// to be updated without shipping new executable versions.
void PopulateWithServerProvidedValues();
- // Map of UUID to blacklisted value.
- std::map<device::BluetoothUUID, Value> blacklisted_uuids_;
+ // Map of UUID to blocklisted value.
+ std::map<device::BluetoothUUID, Value> blocklisted_uuids_;
- DISALLOW_COPY_AND_ASSIGN(BluetoothBlacklist);
+ DISALLOW_COPY_AND_ASSIGN(BluetoothBlocklist);
};
} // namespace content
-#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_blocklist_unittest.cc
index d07121b77ff..9e171ca4eae 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_blocklist_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/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -11,129 +11,121 @@ using device::BluetoothUUID;
namespace content {
-namespace {
-
-base::Optional<BluetoothUUID> Canonicalize(const std::string& str) {
- return base::make_optional(device::BluetoothUUID(str));
-}
-
-} // namespace
-
-class BluetoothBlacklistTest : public ::testing::Test {
+class BluetoothBlocklistTest : public ::testing::Test {
public:
- BluetoothBlacklistTest() : list_(BluetoothBlacklist::Get()) {
- // Because BluetoothBlacklist is used via a singleton instance, the data
+ BluetoothBlocklistTest() : list_(BluetoothBlocklist::Get()) {
+ // Because BluetoothBlocklist is used via a singleton instance, the data
// must be reset for each test.
list_.ResetToDefaultValuesForTest();
}
- BluetoothBlacklist& list_;
+ BluetoothBlocklist& list_;
};
-TEST_F(BluetoothBlacklistTest, NonExcludedUUID) {
+TEST_F(BluetoothBlocklistTest, NonExcludedUUID) {
BluetoothUUID non_excluded_uuid("00000000-0000-0000-0000-000000000000");
EXPECT_FALSE(list_.IsExcluded(non_excluded_uuid));
EXPECT_FALSE(list_.IsExcludedFromReads(non_excluded_uuid));
EXPECT_FALSE(list_.IsExcludedFromWrites(non_excluded_uuid));
}
-TEST_F(BluetoothBlacklistTest, ExcludeUUID) {
+TEST_F(BluetoothBlocklistTest, ExcludeUUID) {
BluetoothUUID excluded_uuid("eeee");
- list_.Add(excluded_uuid, BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(excluded_uuid, BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(list_.IsExcluded(excluded_uuid));
EXPECT_TRUE(list_.IsExcludedFromReads(excluded_uuid));
EXPECT_TRUE(list_.IsExcludedFromWrites(excluded_uuid));
}
-TEST_F(BluetoothBlacklistTest, ExcludeReadsUUID) {
+TEST_F(BluetoothBlocklistTest, ExcludeReadsUUID) {
BluetoothUUID exclude_reads_uuid("eeee");
- list_.Add(exclude_reads_uuid, BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(exclude_reads_uuid, BluetoothBlocklist::Value::EXCLUDE_READS);
EXPECT_FALSE(list_.IsExcluded(exclude_reads_uuid));
EXPECT_TRUE(list_.IsExcludedFromReads(exclude_reads_uuid));
EXPECT_FALSE(list_.IsExcludedFromWrites(exclude_reads_uuid));
}
-TEST_F(BluetoothBlacklistTest, ExcludeWritesUUID) {
+TEST_F(BluetoothBlocklistTest, ExcludeWritesUUID) {
BluetoothUUID exclude_writes_uuid("eeee");
- list_.Add(exclude_writes_uuid, BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(exclude_writes_uuid, BluetoothBlocklist::Value::EXCLUDE_WRITES);
EXPECT_FALSE(list_.IsExcluded(exclude_writes_uuid));
EXPECT_FALSE(list_.IsExcludedFromReads(exclude_writes_uuid));
EXPECT_TRUE(list_.IsExcludedFromWrites(exclude_writes_uuid));
}
-TEST_F(BluetoothBlacklistTest, InvalidUUID) {
+TEST_F(BluetoothBlocklistTest, InvalidUUID) {
BluetoothUUID empty_string_uuid("");
EXPECT_DEATH_IF_SUPPORTED(
- list_.Add(empty_string_uuid, BluetoothBlacklist::Value::EXCLUDE), "");
+ list_.Add(empty_string_uuid, BluetoothBlocklist::Value::EXCLUDE), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(empty_string_uuid), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(empty_string_uuid), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(empty_string_uuid), "");
BluetoothUUID invalid_string_uuid("Not a valid UUID string.");
EXPECT_DEATH_IF_SUPPORTED(
- list_.Add(invalid_string_uuid, BluetoothBlacklist::Value::EXCLUDE), "");
+ list_.Add(invalid_string_uuid, BluetoothBlocklist::Value::EXCLUDE), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(invalid_string_uuid), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(invalid_string_uuid), "");
EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(invalid_string_uuid),
"");
}
-// Abreviated UUIDs used to create, or test against, the blacklist work
+// Abreviated UUIDs used to create, or test against, the blocklist work
// correctly compared to full UUIDs.
-TEST_F(BluetoothBlacklistTest, AbreviatedUUIDs) {
- list_.Add(BluetoothUUID("aaaa"), BluetoothBlacklist::Value::EXCLUDE);
+TEST_F(BluetoothBlocklistTest, AbreviatedUUIDs) {
+ list_.Add(BluetoothUUID("aaaa"), BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(
list_.IsExcluded(BluetoothUUID("0000aaaa-0000-1000-8000-00805f9b34fb")));
list_.Add(BluetoothUUID("0000bbbb-0000-1000-8000-00805f9b34fb"),
- BluetoothBlacklist::Value::EXCLUDE);
+ BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("bbbb")));
}
// Tests permutations of previous values and then Add() with a new value,
// requiring result to be strictest result of the combination.
-TEST_F(BluetoothBlacklistTest, Add_MergingExcludeValues) {
- list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE);
+TEST_F(BluetoothBlocklistTest, Add_MergingExcludeValues) {
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee01")));
- list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlocklist::Value::EXCLUDE_READS);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee02")));
- list_.Add(BluetoothUUID("ee03"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("ee03"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee03"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee03"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee03")));
- list_.Add(BluetoothUUID("ee04"), BluetoothBlacklist::Value::EXCLUDE_READS);
- list_.Add(BluetoothUUID("ee04"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee04"), BluetoothBlocklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee04"), BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee04")));
- list_.Add(BluetoothUUID("ee05"), BluetoothBlacklist::Value::EXCLUDE_READS);
- list_.Add(BluetoothUUID("ee05"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee05"), BluetoothBlocklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee05"), BluetoothBlocklist::Value::EXCLUDE_READS);
EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("ee05")));
EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("ee05")));
- list_.Add(BluetoothUUID("ee06"), BluetoothBlacklist::Value::EXCLUDE_READS);
- list_.Add(BluetoothUUID("ee06"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee06"), BluetoothBlocklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee06"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee06")));
- list_.Add(BluetoothUUID("ee07"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
- list_.Add(BluetoothUUID("ee07"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee07"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee07"), BluetoothBlocklist::Value::EXCLUDE);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee07")));
- list_.Add(BluetoothUUID("ee08"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
- list_.Add(BluetoothUUID("ee08"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee08"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee08"), BluetoothBlocklist::Value::EXCLUDE_READS);
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee08")));
- list_.Add(BluetoothUUID("ee09"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
- list_.Add(BluetoothUUID("ee09"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee09"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee09"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("ee09")));
EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("ee09")));
}
// Tests Add() with string that contains many UUID:exclusion value pairs,
-// checking that the correct blacklist entries are created for them.
-TEST_F(BluetoothBlacklistTest, Add_StringWithValidEntries) {
+// checking that the correct blocklist entries are created for them.
+TEST_F(BluetoothBlocklistTest, Add_StringWithValidEntries) {
list_.Add(
"0001:e,0002:r,0003:w, " // Single items.
"0004:r,0004:r, " // Duplicate items.
@@ -158,7 +150,7 @@ TEST_F(BluetoothBlacklistTest, Add_StringWithValidEntries) {
}
// Tests Add() with strings that contain no valid UUID:exclusion value.
-TEST_F(BluetoothBlacklistTest, Add_StringsWithNoValidEntries) {
+TEST_F(BluetoothBlocklistTest, Add_StringsWithNoValidEntries) {
size_t previous_list_size = list_.size();
list_.Add("");
list_.Add("~!@#$%^&*()-_=+[]{}/*-");
@@ -185,7 +177,7 @@ TEST_F(BluetoothBlacklistTest, Add_StringsWithNoValidEntries) {
// Tests Add() with strings that contain exactly one valid UUID:exclusion value
// pair, and optionally other issues in the string that are ignored.
-TEST_F(BluetoothBlacklistTest, Add_StringsWithOneValidEntry) {
+TEST_F(BluetoothBlocklistTest, Add_StringsWithOneValidEntry) {
size_t previous_list_size = list_.size();
list_.Add("0001:e");
EXPECT_EQ(++previous_list_size, list_.size());
@@ -220,59 +212,76 @@ TEST_F(BluetoothBlacklistTest, Add_StringsWithOneValidEntry) {
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0009")));
}
-TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsFalse) {
- list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE_READS);
- list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+TEST_F(BluetoothBlocklistTest, IsExcluded_BluetoothScanFilter_ReturnsFalse) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlocklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
{
- mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> empty_filters;
+ std::vector<blink::mojom::WebBluetoothScanFilterPtr> empty_filters;
EXPECT_FALSE(list_.IsExcluded(empty_filters));
}
{
- mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> single_empty_filter(1);
+ std::vector<blink::mojom::WebBluetoothScanFilterPtr>
+ single_filter_with_no_services(1);
+
+ single_filter_with_no_services[0] =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ EXPECT_FALSE(single_filter_with_no_services[0]->services);
+ EXPECT_FALSE(list_.IsExcluded(single_filter_with_no_services));
+ }
+ {
+ std::vector<blink::mojom::WebBluetoothScanFilterPtr> single_empty_filter(1);
single_empty_filter[0] = blink::mojom::WebBluetoothScanFilter::New();
- single_empty_filter[0]->services =
- mojo::Array<base::Optional<BluetoothUUID>>();
+ single_empty_filter[0]->services.emplace();
- EXPECT_EQ(0u, single_empty_filter[0]->services.size());
+ EXPECT_EQ(0u, single_empty_filter[0]->services->size());
EXPECT_FALSE(list_.IsExcluded(single_empty_filter));
}
{
- mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>
+ std::vector<blink::mojom::WebBluetoothScanFilterPtr>
single_non_matching_filter(1);
single_non_matching_filter[0] = blink::mojom::WebBluetoothScanFilter::New();
- single_non_matching_filter[0]->services.push_back(Canonicalize("0000"));
+ single_non_matching_filter[0]->services.emplace();
+ single_non_matching_filter[0]->services->push_back(BluetoothUUID("0000"));
EXPECT_FALSE(list_.IsExcluded(single_non_matching_filter));
}
{
- mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>
+ std::vector<blink::mojom::WebBluetoothScanFilterPtr>
multiple_non_matching_filters(2);
multiple_non_matching_filters[0] =
blink::mojom::WebBluetoothScanFilter::New();
- multiple_non_matching_filters[0]->services.push_back(Canonicalize("0000"));
- multiple_non_matching_filters[0]->services.push_back(Canonicalize("ee01"));
+ multiple_non_matching_filters[0]->services.emplace();
+ multiple_non_matching_filters[0]->services->push_back(
+ BluetoothUUID("0000"));
+ multiple_non_matching_filters[0]->services->push_back(
+ BluetoothUUID("ee01"));
multiple_non_matching_filters[1] =
blink::mojom::WebBluetoothScanFilter::New();
- multiple_non_matching_filters[1]->services.push_back(Canonicalize("ee02"));
- multiple_non_matching_filters[1]->services.push_back(Canonicalize("0003"));
+ multiple_non_matching_filters[1]->services.emplace();
+ multiple_non_matching_filters[1]->services->push_back(
+ BluetoothUUID("ee02"));
+ multiple_non_matching_filters[1]->services->push_back(
+ BluetoothUUID("0003"));
EXPECT_FALSE(list_.IsExcluded(multiple_non_matching_filters));
}
}
-TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
- list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
+TEST_F(BluetoothBlocklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlocklist::Value::EXCLUDE);
{
mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> single_matching_filter(
1);
single_matching_filter[0] = blink::mojom::WebBluetoothScanFilter::New();
- single_matching_filter[0]->services.push_back(Canonicalize("eeee"));
+ single_matching_filter[0]->services.emplace();
+ single_matching_filter[0]->services->push_back(BluetoothUUID("eeee"));
EXPECT_TRUE(list_.IsExcluded(single_matching_filter));
}
@@ -281,12 +290,14 @@ TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
2);
first_matching_filter[0] = blink::mojom::WebBluetoothScanFilter::New();
- first_matching_filter[0]->services.push_back(Canonicalize("eeee"));
- first_matching_filter[0]->services.push_back(Canonicalize("0001"));
+ first_matching_filter[0]->services.emplace();
+ first_matching_filter[0]->services->push_back(BluetoothUUID("eeee"));
+ first_matching_filter[0]->services->push_back(BluetoothUUID("0001"));
first_matching_filter[1] = blink::mojom::WebBluetoothScanFilter::New();
- first_matching_filter[1]->services.push_back(Canonicalize("0002"));
- first_matching_filter[1]->services.push_back(Canonicalize("0003"));
+ first_matching_filter[1]->services.emplace();
+ first_matching_filter[1]->services->push_back(BluetoothUUID("0002"));
+ first_matching_filter[1]->services->push_back(BluetoothUUID("0003"));
EXPECT_TRUE(list_.IsExcluded(first_matching_filter));
}
@@ -295,12 +306,14 @@ TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
2);
last_matching_filter[0] = blink::mojom::WebBluetoothScanFilter::New();
- last_matching_filter[0]->services.push_back(Canonicalize("0001"));
- last_matching_filter[0]->services.push_back(Canonicalize("0001"));
+ last_matching_filter[0]->services.emplace();
+ last_matching_filter[0]->services->push_back(BluetoothUUID("0001"));
+ last_matching_filter[0]->services->push_back(BluetoothUUID("0001"));
last_matching_filter[1] = blink::mojom::WebBluetoothScanFilter::New();
- last_matching_filter[1]->services.push_back(Canonicalize("0002"));
- last_matching_filter[1]->services.push_back(Canonicalize("eeee"));
+ last_matching_filter[1]->services.emplace();
+ last_matching_filter[1]->services->push_back(BluetoothUUID("0002"));
+ last_matching_filter[1]->services->push_back(BluetoothUUID("eeee"));
EXPECT_TRUE(list_.IsExcluded(last_matching_filter));
}
@@ -309,113 +322,111 @@ TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
multiple_matching_filters(2);
multiple_matching_filters[0] = blink::mojom::WebBluetoothScanFilter::New();
- multiple_matching_filters[0]->services.push_back(Canonicalize("eeee"));
- multiple_matching_filters[0]->services.push_back(Canonicalize("eeee"));
+ multiple_matching_filters[0]->services.emplace();
+ multiple_matching_filters[0]->services->push_back(BluetoothUUID("eeee"));
+ multiple_matching_filters[0]->services->push_back(BluetoothUUID("eeee"));
multiple_matching_filters[1] = blink::mojom::WebBluetoothScanFilter::New();
- multiple_matching_filters[1]->services.push_back(Canonicalize("eeee"));
- multiple_matching_filters[1]->services.push_back(Canonicalize("eeee"));
+ multiple_matching_filters[1]->services.emplace();
+ multiple_matching_filters[1]->services->push_back(BluetoothUUID("eeee"));
+ multiple_matching_filters[1]->services->push_back(BluetoothUUID("eeee"));
EXPECT_TRUE(list_.IsExcluded(multiple_matching_filters));
}
}
-TEST_F(BluetoothBlacklistTest, RemoveExcludedUUIDs_NonMatching) {
- list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE_READS);
- list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+TEST_F(BluetoothBlocklistTest, RemoveExcludedUUIDs_NonMatching) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlocklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlocklist::Value::EXCLUDE_WRITES);
// options.optional_services should be the same before and after
// RemoveExcludedUUIDs().
{
// Empty optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services = mojo::Array<base::Optional<BluetoothUUID>>();
- mojo::Array<base::Optional<BluetoothUUID>> expected =
- options.optional_services.Clone();
+ std::vector<BluetoothUUID> expected = options.optional_services;
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
{
// One non-matching service in optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services.push_back(Canonicalize("0000"));
+ options.optional_services.push_back(BluetoothUUID("0000"));
- mojo::Array<base::Optional<BluetoothUUID>> expected =
- options.optional_services.Clone();
+ std::vector<BluetoothUUID> expected = options.optional_services;
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
{
// Multiple non-matching services in optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services.push_back(Canonicalize("0000"));
- options.optional_services.push_back(Canonicalize("ee01"));
- options.optional_services.push_back(Canonicalize("ee02"));
- options.optional_services.push_back(Canonicalize("0003"));
+ options.optional_services.push_back(BluetoothUUID("0000"));
+ options.optional_services.push_back(BluetoothUUID("ee01"));
+ options.optional_services.push_back(BluetoothUUID("ee02"));
+ options.optional_services.push_back(BluetoothUUID("0003"));
- mojo::Array<base::Optional<BluetoothUUID>> expected =
- options.optional_services.Clone();
+ std::vector<BluetoothUUID> expected = options.optional_services;
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
}
-TEST_F(BluetoothBlacklistTest, RemoveExcludedUuids_Matching) {
- list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("eee2"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("eee3"), BluetoothBlacklist::Value::EXCLUDE);
- list_.Add(BluetoothUUID("eee4"), BluetoothBlacklist::Value::EXCLUDE);
+TEST_F(BluetoothBlocklistTest, RemoveExcludedUuids_Matching) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee2"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee3"), BluetoothBlocklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee4"), BluetoothBlocklist::Value::EXCLUDE);
{
// Single matching service in optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services.push_back(Canonicalize("eeee"));
+ options.optional_services.push_back(BluetoothUUID("eeee"));
- mojo::Array<base::Optional<BluetoothUUID>> expected;
+ std::vector<BluetoothUUID> expected;
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
{
// Single matching of many services in optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services.push_back(Canonicalize("0000"));
- options.optional_services.push_back(Canonicalize("eeee"));
- options.optional_services.push_back(Canonicalize("0001"));
+ options.optional_services.push_back(BluetoothUUID("0000"));
+ options.optional_services.push_back(BluetoothUUID("eeee"));
+ options.optional_services.push_back(BluetoothUUID("0001"));
- mojo::Array<base::Optional<BluetoothUUID>> expected;
- expected.push_back(Canonicalize("0000"));
- expected.push_back(Canonicalize("0001"));
+ std::vector<BluetoothUUID> expected;
+ expected.push_back(BluetoothUUID("0000"));
+ expected.push_back(BluetoothUUID("0001"));
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
{
// All matching of many services in optional_services.
blink::mojom::WebBluetoothRequestDeviceOptions options;
- options.optional_services.push_back(Canonicalize("eee2"));
- options.optional_services.push_back(Canonicalize("eee4"));
- options.optional_services.push_back(Canonicalize("eee3"));
- options.optional_services.push_back(Canonicalize("eeee"));
+ options.optional_services.push_back(BluetoothUUID("eee2"));
+ options.optional_services.push_back(BluetoothUUID("eee4"));
+ options.optional_services.push_back(BluetoothUUID("eee3"));
+ options.optional_services.push_back(BluetoothUUID("eeee"));
- mojo::Array<base::Optional<BluetoothUUID>> expected;
+ std::vector<BluetoothUUID> expected;
list_.RemoveExcludedUUIDs(&options);
- EXPECT_TRUE(options.optional_services.Equals(expected));
+ EXPECT_EQ(expected, options.optional_services);
}
}
-TEST_F(BluetoothBlacklistTest, VerifyDefaultBlacklistSize) {
- // REMINDER: ADD new blacklist items to tests below for each exclusion type.
+TEST_F(BluetoothBlocklistTest, VerifyDefaultBlocklistSize) {
+ // REMINDER: ADD new blocklist items to tests below for each exclusion type.
EXPECT_EQ(13u, list_.size());
}
-TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeList) {
+TEST_F(BluetoothBlocklistTest, VerifyDefaultExcludeList) {
EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("1800")));
EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("1801")));
EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("1812")));
@@ -438,7 +449,7 @@ TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeList) {
list_.IsExcluded(BluetoothUUID("bad3ec61-3cc3-4954-9702-7977df514114")));
}
-TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeReadList) {
+TEST_F(BluetoothBlocklistTest, VerifyDefaultExcludeReadList) {
EXPECT_FALSE(list_.IsExcludedFromReads(BluetoothUUID("1800")));
EXPECT_FALSE(list_.IsExcludedFromReads(BluetoothUUID("1801")));
EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("1812")));
@@ -461,7 +472,7 @@ TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeReadList) {
BluetoothUUID("bad3ec61-3cc3-4954-9702-7977df514114")));
}
-TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeWriteList) {
+TEST_F(BluetoothBlocklistTest, VerifyDefaultExcludeWriteList) {
EXPECT_FALSE(list_.IsExcludedFromWrites(BluetoothUUID("1800")));
EXPECT_FALSE(list_.IsExcludedFromWrites(BluetoothUUID("1801")));
EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("1812")));
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index 3c53e2cf8fa..5d444c8453b 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -10,9 +10,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "content/browser/bluetooth/bluetooth_metrics.h"
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -25,6 +26,7 @@
#include "device/bluetooth/bluetooth_discovery_session.h"
using device::BluetoothUUID;
+using UUIDSet = device::BluetoothDevice::UUIDSet;
namespace {
@@ -35,6 +37,13 @@ const int kMaxRSSI = -55;
// Number of RSSI levels used in the signal strength image.
const int kNumSignalStrengthLevels = 5;
+const content::UMARSSISignalStrengthLevel kRSSISignalStrengthEnumTable[] = {
+ content::UMARSSISignalStrengthLevel::LEVEL_0,
+ content::UMARSSISignalStrengthLevel::LEVEL_1,
+ content::UMARSSISignalStrengthLevel::LEVEL_2,
+ content::UMARSSISignalStrengthLevel::LEVEL_3,
+ content::UMARSSISignalStrengthLevel::LEVEL_4};
+
} // namespace
namespace content {
@@ -46,26 +55,31 @@ constexpr size_t kMaxLengthForDeviceName =
29; // max length of device name in filter.
// The duration of a Bluetooth Scan in seconds.
-constexpr int kScanDuration = 10;
+constexpr int kScanDuration = 60;
constexpr int kTestScanDuration = 0;
void LogRequestDeviceOptions(
const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
VLOG(1) << "requestDevice called with the following filters: ";
+ VLOG(1) << "acceptAllDevices: " << options->accept_all_devices;
+
+ if (!options->filters)
+ return;
+
int i = 0;
- for (const auto& filter : options->filters) {
+ for (const auto& filter : options->filters.value()) {
VLOG(1) << "Filter #" << ++i;
- if (!filter->name.is_null())
- VLOG(1) << "Name: " << filter->name;
+ if (filter->name)
+ VLOG(1) << "Name: " << filter->name.value();
- if (!filter->name_prefix.is_null())
- VLOG(1) << "Name Prefix: " << filter->name_prefix;
+ if (filter->name_prefix)
+ VLOG(1) << "Name Prefix: " << filter->name_prefix.value();
- if (!filter->services.is_null()) {
+ if (filter->services) {
VLOG(1) << "Services: ";
VLOG(1) << "\t[";
- for (const auto& service : filter->services)
- VLOG(1) << "\t\t" << service->canonical_value();
+ for (const auto& service : filter->services.value())
+ VLOG(1) << "\t\t" << service.canonical_value();
VLOG(1) << "\t]";
}
}
@@ -74,52 +88,65 @@ void LogRequestDeviceOptions(
bool IsEmptyOrInvalidFilter(
const blink::mojom::WebBluetoothScanFilterPtr& filter) {
// At least one member needs to be present.
- if (filter->name.is_null() && filter->name_prefix.is_null() &&
- filter->services.is_null())
+ if (!filter->name && !filter->name_prefix && !filter->services)
return true;
// The renderer will never send a name or a name_prefix longer than
// kMaxLengthForDeviceName.
- if (!filter->name.is_null() && filter->name.size() > kMaxLengthForDeviceName)
+ if (filter->name && filter->name->size() > kMaxLengthForDeviceName)
return true;
- if (!filter->name_prefix.is_null() && filter->name_prefix.size() == 0)
+ if (filter->name_prefix && filter->name_prefix->size() == 0)
return true;
- if (!filter->name_prefix.is_null() &&
- filter->name_prefix.size() > kMaxLengthForDeviceName)
+ if (filter->name_prefix &&
+ filter->name_prefix->size() > kMaxLengthForDeviceName)
return true;
return false;
}
bool HasEmptyOrInvalidFilter(
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
- return filters.empty()
+ const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+ filters) {
+ if (!filters) {
+ return true;
+ }
+
+ return filters->empty()
? true
- : filters.end() != std::find_if(filters.begin(), filters.end(),
- IsEmptyOrInvalidFilter);
+ : filters->end() != std::find_if(filters->begin(), filters->end(),
+ IsEmptyOrInvalidFilter);
+}
+
+bool IsOptionsInvalid(
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
+ if (options->accept_all_devices) {
+ return options->filters.has_value();
+ } else {
+ return HasEmptyOrInvalidFilter(options->filters);
+ }
}
-bool MatchesFilter(const device::BluetoothDevice& device,
+bool MatchesFilter(const std::string* device_name,
+ const UUIDSet& device_uuids,
const blink::mojom::WebBluetoothScanFilterPtr& filter) {
- if (!filter->name.is_null()) {
- if (!device.GetName())
+ if (filter->name) {
+ if (device_name == nullptr)
return false;
- if (filter->name != device.GetName().value())
+ if (filter->name.value() != *device_name)
return false;
}
- if (!filter->name_prefix.is_null() && filter->name_prefix.size()) {
- if (!device.GetName())
+ if (filter->name_prefix && filter->name_prefix->size()) {
+ if (device_name == nullptr)
return false;
- if (!base::StartsWith(device.GetName().value(), filter->name_prefix.get(),
+ if (!base::StartsWith(*device_name, filter->name_prefix.value(),
base::CompareCase::SENSITIVE))
return false;
}
- if (!filter->services.is_null()) {
- const device::BluetoothDevice::UUIDSet& device_uuids = device.GetUUIDs();
- for (const base::Optional<BluetoothUUID>& service : filter->services) {
- if (!base::ContainsKey(device_uuids, service.value())) {
+ if (filter->services) {
+ for (const auto& service : filter->services.value()) {
+ if (!base::ContainsKey(device_uuids, service)) {
return false;
}
}
@@ -129,11 +156,13 @@ bool MatchesFilter(const device::BluetoothDevice& device,
}
bool MatchesFilters(
- const device::BluetoothDevice& device,
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ const std::string* device_name,
+ const UUIDSet& device_uuids,
+ const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+ filters) {
DCHECK(!HasEmptyOrInvalidFilter(filters));
- for (const auto& filter : filters) {
- if (MatchesFilter(device, filter)) {
+ for (const auto& filter : filters.value()) {
+ if (MatchesFilter(device_name, device_uuids, filter)) {
return true;
}
}
@@ -141,13 +170,21 @@ bool MatchesFilters(
}
std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter(
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ const base::Optional<std::vector<blink::mojom::WebBluetoothScanFilterPtr>>&
+ filters) {
std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services;
- for (const auto& filter : filters) {
- for (const base::Optional<BluetoothUUID>& service : filter->services) {
- services.insert(service.value());
+
+ if (filters) {
+ for (const auto& filter : filters.value()) {
+ if (!filter->services) {
+ continue;
+ }
+ for (const auto& service : filter->services.value()) {
+ services.insert(service);
+ }
}
}
+
// There isn't much support for GATT over BR/EDR from neither platforms nor
// devices so performing a Dual scan will find devices that the API is not
// able to interact with. To avoid wasting power and confusing users with
@@ -188,15 +225,17 @@ UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) {
NOTREACHED();
return UMARequestDeviceOutcome::SUCCESS;
case BluetoothChooser::Event::RESCAN:
- // Rescanning doesn't result in a IPC message for the request being sent
- // so no need to histogram it.
- NOTREACHED();
- return UMARequestDeviceOutcome::SUCCESS;
+ return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_RESCAN;
}
NOTREACHED();
return UMARequestDeviceOutcome::SUCCESS;
}
+void RecordScanningDuration(const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_LONG_TIMES("Bluetooth.Web.RequestDevice.ScanningDuration",
+ duration);
+}
+
} // namespace
BluetoothDeviceChooserController::BluetoothDeviceChooserController(
@@ -223,9 +262,14 @@ BluetoothDeviceChooserController::BluetoothDeviceChooserController(
}
BluetoothDeviceChooserController::~BluetoothDeviceChooserController() {
+ if (scanning_start_time_) {
+ RecordScanningDuration(base::TimeTicks::Now() -
+ scanning_start_time_.value());
+ }
+
if (chooser_) {
DCHECK(!error_callback_.is_null());
- error_callback_.Run(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ error_callback_.Run(blink::mojom::WebBluetoothResult::CHOOSER_CANCELLED);
}
}
@@ -242,24 +286,25 @@ void BluetoothDeviceChooserController::GetDevice(
success_callback_ = success_callback;
error_callback_ = error_callback;
- // The renderer should never send empty filters.
- if (HasEmptyOrInvalidFilter(options->filters)) {
+ // The renderer should never send invalid options.
+ if (IsOptionsInvalid(options)) {
web_bluetooth_service_->CrashRendererAndClosePipe(
- bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
+ bad_message::BDH_INVALID_OPTIONS);
return;
}
options_ = std::move(options);
LogRequestDeviceOptions(options_);
- // Check blacklist to reject invalid filters and adjust optional_services.
- if (BluetoothBlacklist::Get().IsExcluded(options_->filters)) {
+ // Check blocklist to reject invalid filters and adjust optional_services.
+ if (options_->filters &&
+ BluetoothBlocklist::Get().IsExcluded(options_->filters.value())) {
RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER);
+ UMARequestDeviceOutcome::BLOCKLISTED_SERVICE_IN_FILTER);
PostErrorCallback(
- blink::mojom::WebBluetoothError::REQUEST_DEVICE_WITH_BLACKLISTED_UUID);
+ blink::mojom::WebBluetoothResult::REQUEST_DEVICE_WITH_BLOCKLISTED_UUID);
return;
}
- BluetoothBlacklist::Get().RemoveExcludedUUIDs(options_.get());
+ BluetoothBlocklist::Get().RemoveExcludedUUIDs(options_.get());
const url::Origin requesting_origin =
render_frame_host_->GetLastCommittedOrigin();
@@ -270,7 +315,7 @@ void BluetoothDeviceChooserController::GetDevice(
// matching origins. When relaxing this, take care to handle non-sandboxed
// unique origins.
if (!embedding_origin.IsSameOriginWith(requesting_origin)) {
- PostErrorCallback(blink::mojom::WebBluetoothError::
+ PostErrorCallback(blink::mojom::WebBluetoothResult::
REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME);
return;
}
@@ -282,7 +327,7 @@ void BluetoothDeviceChooserController::GetDevice(
VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
RecordRequestDeviceOutcome(
UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
- PostErrorCallback(blink::mojom::WebBluetoothError::NO_BLUETOOTH_ADAPTER);
+ PostErrorCallback(blink::mojom::WebBluetoothResult::NO_BLUETOOTH_ADAPTER);
return;
}
@@ -292,7 +337,7 @@ void BluetoothDeviceChooserController::GetDevice(
case ContentBrowserClient::AllowWebBluetoothResult::BLOCK_POLICY: {
RecordRequestDeviceOutcome(
UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_POLICY_DISABLED);
- PostErrorCallback(blink::mojom::WebBluetoothError::
+ PostErrorCallback(blink::mojom::WebBluetoothResult::
CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED);
return;
}
@@ -305,7 +350,7 @@ void BluetoothDeviceChooserController::GetDevice(
// Block requests.
RecordRequestDeviceOutcome(
UMARequestDeviceOutcome::BLUETOOTH_GLOBALLY_DISABLED);
- PostErrorCallback(blink::mojom::WebBluetoothError::
+ PostErrorCallback(blink::mojom::WebBluetoothResult::
CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED);
return;
}
@@ -324,7 +369,7 @@ void BluetoothDeviceChooserController::GetDevice(
if (!chooser_.get()) {
PostErrorCallback(
- blink::mojom::WebBluetoothError::WEB_BLUETOOTH_NOT_SUPPORTED);
+ blink::mojom::WebBluetoothResult::WEB_BLUETOOTH_NOT_SUPPORTED);
return;
}
@@ -352,13 +397,18 @@ void BluetoothDeviceChooserController::GetDevice(
void BluetoothDeviceChooserController::AddFilteredDevice(
const device::BluetoothDevice& device) {
- if (chooser_.get() && MatchesFilters(device, options_->filters)) {
- base::Optional<int8_t> rssi = device.GetInquiryRSSI();
- chooser_->AddOrUpdateDevice(
- device.GetAddress(), !!device.GetName() /* should_update_name */,
- device.GetNameForDisplay(), device.IsGattConnected(),
- web_bluetooth_service_->IsDevicePaired(device.GetAddress()),
- rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1);
+ base::Optional<std::string> device_name = device.GetName();
+ if (chooser_.get()) {
+ if (options_->accept_all_devices ||
+ MatchesFilters(device_name ? &device_name.value() : nullptr,
+ device.GetUUIDs(), options_->filters)) {
+ base::Optional<int8_t> rssi = device.GetInquiryRSSI();
+ chooser_->AddOrUpdateDevice(
+ device.GetAddress(), !!device.GetName() /* should_update_name */,
+ device.GetNameForDisplay(), device.IsGattConnected(),
+ web_bluetooth_service_->IsDevicePaired(device.GetAddress()),
+ rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1);
+ }
}
}
@@ -384,15 +434,26 @@ void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) {
int BluetoothDeviceChooserController::CalculateSignalStrengthLevel(
int8_t rssi) {
- if (rssi <= kMinRSSI)
+ RecordRSSISignalStrength(rssi);
+
+ if (rssi <= kMinRSSI) {
+ RecordRSSISignalStrengthLevel(
+ UMARSSISignalStrengthLevel::LESS_THAN_OR_EQUAL_TO_MIN_RSSI);
return 0;
+ }
- if (rssi >= kMaxRSSI)
+ if (rssi >= kMaxRSSI) {
+ RecordRSSISignalStrengthLevel(
+ UMARSSISignalStrengthLevel::GREATER_THAN_OR_EQUAL_TO_MAX_RSSI);
return kNumSignalStrengthLevels - 1;
+ }
double input_range = kMaxRSSI - kMinRSSI;
double output_range = kNumSignalStrengthLevels - 1;
- return static_cast<int>((rssi - kMinRSSI) * output_range / input_range);
+ int level = static_cast<int>((rssi - kMinRSSI) * output_range / input_range);
+ DCHECK(kNumSignalStrengthLevels == arraysize(kRSSISignalStrengthEnumTable));
+ RecordRSSISignalStrengthLevel(kRSSISignalStrengthEnumTable[level]);
+ return level;
}
void BluetoothDeviceChooserController::SetTestScanDurationForTesting() {
@@ -416,6 +477,8 @@ void BluetoothDeviceChooserController::StartDeviceDiscovery() {
return;
}
+ scanning_start_time_ = base::TimeTicks::Now();
+
chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::DISCOVERING);
adapter_->StartDiscoverySessionWithFilter(
ComputeScanFilter(options_->filters),
@@ -429,6 +492,13 @@ void BluetoothDeviceChooserController::StartDeviceDiscovery() {
void BluetoothDeviceChooserController::StopDeviceDiscovery() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (scanning_start_time_) {
+ RecordScanningDuration(base::TimeTicks::Now() -
+ scanning_start_time_.value());
+ scanning_start_time_.reset();
+ }
+
StopDiscoverySession(std::move(discovery_session_));
if (chooser_) {
chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::IDLE);
@@ -463,6 +533,7 @@ void BluetoothDeviceChooserController::OnBluetoothChooserEvent(
switch (event) {
case BluetoothChooser::Event::RESCAN:
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
PopulateConnectedDevices();
DCHECK(chooser_);
StartDeviceDiscovery();
@@ -470,29 +541,31 @@ void BluetoothDeviceChooserController::OnBluetoothChooserEvent(
return;
case BluetoothChooser::Event::DENIED_PERMISSION:
RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- PostErrorCallback(blink::mojom::WebBluetoothError::
+ PostErrorCallback(blink::mojom::WebBluetoothResult::
CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN);
break;
case BluetoothChooser::Event::CANCELLED:
RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ PostErrorCallback(blink::mojom::WebBluetoothResult::CHOOSER_CANCELLED);
break;
case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
VLOG(1) << "Overview Help link pressed.";
RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ PostErrorCallback(blink::mojom::WebBluetoothResult::CHOOSER_CANCELLED);
break;
case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
VLOG(1) << "Adapter Off Help link pressed.";
RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ PostErrorCallback(blink::mojom::WebBluetoothResult::CHOOSER_CANCELLED);
break;
case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
VLOG(1) << "Need Location Help link pressed.";
RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ PostErrorCallback(blink::mojom::WebBluetoothResult::CHOOSER_CANCELLED);
break;
case BluetoothChooser::Event::SELECTED:
+ // RecordRequestDeviceOutcome is called in the callback, because the
+ // device may have vanished.
PostSuccessCallback(device_address);
break;
}
@@ -511,7 +584,7 @@ void BluetoothDeviceChooserController::PostSuccessCallback(
}
void BluetoothDeviceChooserController::PostErrorCallback(
- blink::mojom::WebBluetoothError error) {
+ blink::mojom::WebBluetoothResult error) {
if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(error_callback_, error))) {
LOG(WARNING) << "No TaskRunner.";
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
index b9e21cc5568..500d31b144c 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
@@ -17,7 +18,6 @@
namespace device {
class BluetoothAdapter;
class BluetoothDevice;
-class BluetoothDiscoveryFilter;
class BluetoothDiscoverySession;
}
@@ -35,7 +35,7 @@ class CONTENT_EXPORT BluetoothDeviceChooserController final {
typedef base::Callback<void(blink::mojom::WebBluetoothRequestDeviceOptionsPtr,
const std::string& device_address)>
SuccessCallback;
- typedef base::Callback<void(blink::mojom::WebBluetoothError error)>
+ typedef base::Callback<void(blink::mojom::WebBluetoothResult result)>
ErrorCallback;
// |web_bluetooth_service_| service that owns this class.
@@ -51,7 +51,7 @@ class CONTENT_EXPORT BluetoothDeviceChooserController final {
// This function performs the following checks before starting a discovery
// session:
// - Validates filters in |request_device_options|.
- // - Removes any blacklisted UUIDs from
+ // - Removes any blocklisted UUIDs from
// |request_device_options.optinal_services|.
// - Checks if the request came from a cross-origin iframe.
// - Checks if the request came from a unique origin.
@@ -112,7 +112,7 @@ class CONTENT_EXPORT BluetoothDeviceChooserController final {
// Helper function to asynchronously run success_callback_.
void PostSuccessCallback(const std::string& device_address);
// Helper function to asynchronously run error_callback_.
- void PostErrorCallback(blink::mojom::WebBluetoothError error);
+ void PostErrorCallback(blink::mojom::WebBluetoothResult result);
// If true all new instances of this class will have a scan duration of 0.
static bool use_test_scan_duration_;
@@ -146,6 +146,9 @@ class CONTENT_EXPORT BluetoothDeviceChooserController final {
// http://crbug.com/611852
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_;
+ // The time when scanning starts.
+ base::Optional<base::TimeTicks> scanning_start_time_;
+
// Weak pointer factory for generating 'this' pointers that might live longer
// than we do.
// Note: This should remain the last member so it'll be destroyed and
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.cc b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
index 21fb8dd04e5..7a0b4722f7d 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
@@ -63,13 +63,16 @@ void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) {
}
static void RecordRequestDeviceFilters(
- const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.Filters.Count",
filters.size());
for (const auto& filter : filters) {
+ if (!filter->services) {
+ continue;
+ }
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.FilterSize",
- filter->services.size());
- for (const base::Optional<BluetoothUUID>& service : filter->services) {
+ filter->services->size());
+ for (const BluetoothUUID& service : filter->services.value()) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
UMA_HISTOGRAM_SPARSE_SLOWLY(
@@ -79,10 +82,10 @@ static void RecordRequestDeviceFilters(
}
static void RecordRequestDeviceOptionalServices(
- const mojo::Array<base::Optional<BluetoothUUID>>& optional_services) {
+ const std::vector<BluetoothUUID>& optional_services) {
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.OptionalServices.Count",
optional_services.size());
- for (const base::Optional<BluetoothUUID>& service : optional_services) {
+ for (const BluetoothUUID& service : optional_services) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
UMA_HISTOGRAM_SPARSE_SLOWLY(
@@ -94,14 +97,18 @@ static void RecordRequestDeviceOptionalServices(
static void RecordUnionOfServices(
const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
std::unordered_set<std::string> union_of_services;
- for (const base::Optional<BluetoothUUID>& service :
- options->optional_services) {
- union_of_services.insert(service->canonical_value());
+ for (const BluetoothUUID& service : options->optional_services) {
+ union_of_services.insert(service.canonical_value());
}
- for (const auto& filter : options->filters) {
- for (const base::Optional<BluetoothUUID>& service : filter->services) {
- union_of_services.insert(service->canonical_value());
+ if (options->filters) {
+ for (const auto& filter : options->filters.value()) {
+ if (!filter->services) {
+ continue;
+ }
+ for (const BluetoothUUID& service : filter->services.value()) {
+ union_of_services.insert(service.canonical_value());
+ }
}
}
@@ -119,7 +126,13 @@ static void RecordUnionOfServices(
void RecordRequestDeviceOptions(
const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
- RecordRequestDeviceFilters(options->filters);
+ UMA_HISTOGRAM_BOOLEAN("Bluetooth.Web.RequestDevice.Options.AcceptAllDevices",
+ options->accept_all_devices);
+
+ if (options->filters) {
+ RecordRequestDeviceFilters(options->filters.value());
+ }
+
RecordRequestDeviceOptionalServices(options->optional_services);
RecordUnionOfServices(options);
}
@@ -328,4 +341,16 @@ void RecordStartNotificationsOutcome(CacheQueryOutcome outcome) {
TranslateCacheQueryOutcomeToGATTOperationOutcome(outcome));
}
+void RecordRSSISignalStrength(int rssi) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.RequestDevice.RSSISignalStrength",
+ rssi);
+}
+
+void RecordRSSISignalStrengthLevel(UMARSSISignalStrengthLevel level) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Bluetooth.Web.RequestDevice.RSSISignalStrengthLevel",
+ static_cast<int>(level),
+ static_cast<int>(UMARSSISignalStrengthLevel::COUNT));
+}
+
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.h b/chromium/content/browser/bluetooth/bluetooth_metrics.h
index d3506c3dad2..76e635724da 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.h
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.h
@@ -19,7 +19,6 @@ class BluetoothUUID;
}
namespace content {
-struct BluetoothScanFilter;
// General Metrics
@@ -67,7 +66,7 @@ enum class UMARequestDeviceOutcome {
CHOSEN_DEVICE_VANISHED = 8,
BLUETOOTH_CHOOSER_CANCELLED = 9,
BLUETOOTH_CHOOSER_DENIED_PERMISSION = 10,
- BLACKLISTED_SERVICE_IN_FILTER = 11,
+ BLOCKLISTED_SERVICE_IN_FILTER = 11,
BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED = 12,
ADAPTER_OFF_HELP_LINK_PRESSED = 13,
NEED_LOCATION_HELP_LINK_PRESSED = 14,
@@ -75,6 +74,7 @@ enum class UMARequestDeviceOutcome {
BLUETOOTH_GLOBALLY_DISABLED = 16,
BLUETOOTH_CHOOSER_EVENT_HANDLER_INVALID = 17,
BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE = 18,
+ BLUETOOTH_CHOOSER_RESCAN = 19,
// NOTE: Add new requestDevice() outcomes immediately above this line. Make
// sure to update the enum list in
// tools/metrics/histograms/histograms.xml accordingly.
@@ -178,7 +178,7 @@ enum class UMAGetCharacteristicOutcome {
NO_DEVICE = 1,
NO_SERVICE = 2,
NOT_FOUND = 3,
- BLACKLISTED = 4,
+ BLOCKLISTED = 4,
NO_CHARACTERISTICS = 5,
// Note: Add new outcomes immediately above this line.
// Make sure to update the enum list in
@@ -225,7 +225,7 @@ enum UMAGATTOperationOutcome {
NOT_AUTHORIZED = 10,
NOT_PAIRED = 11,
NOT_SUPPORTED = 12,
- BLACKLISTED = 13,
+ BLOCKLISTED = 13,
// Note: Add new GATT Outcomes immediately above this line.
// Make sure to update the enum list in
// tools/metrics/histograms/histograms.xml accordingly.
@@ -276,6 +276,24 @@ void RecordStartNotificationsOutcome(UMAGATTOperationOutcome outcome);
// called if QueryCacheForCharacteristic fails.
void RecordStartNotificationsOutcome(CacheQueryOutcome outcome);
+enum class UMARSSISignalStrengthLevel {
+ LESS_THAN_OR_EQUAL_TO_MIN_RSSI,
+ LEVEL_0,
+ LEVEL_1,
+ LEVEL_2,
+ LEVEL_3,
+ LEVEL_4,
+ GREATER_THAN_OR_EQUAL_TO_MAX_RSSI,
+ // Note: Add new RSSI signal strength level immediately above this line.
+ COUNT
+};
+
+// Records the raw RSSI, and processed result displayed to users, when
+// content::BluetoothDeviceChooserController::CalculateSignalStrengthLevel() is
+// called.
+void RecordRSSISignalStrength(int rssi);
+void RecordRSSISignalStrengthLevel(UMARSSISignalStrengthLevel level);
+
} // namespace content
#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_METRICS_H_
diff --git a/chromium/content/browser/bluetooth/cache_query_result.h b/chromium/content/browser/bluetooth/cache_query_result.h
index 6f187dbc44c..19c202f5f4b 100644
--- a/chromium/content/browser/bluetooth/cache_query_result.h
+++ b/chromium/content/browser/bluetooth/cache_query_result.h
@@ -27,21 +27,22 @@ struct CacheQueryResult {
~CacheQueryResult() {}
- blink::mojom::WebBluetoothError GetWebError() const {
+ blink::mojom::WebBluetoothResult GetWebResult() const {
switch (outcome) {
case CacheQueryOutcome::SUCCESS:
case CacheQueryOutcome::BAD_RENDERER:
NOTREACHED();
- return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothResult::DEVICE_NO_LONGER_IN_RANGE;
case CacheQueryOutcome::NO_DEVICE:
- return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothResult::DEVICE_NO_LONGER_IN_RANGE;
case CacheQueryOutcome::NO_SERVICE:
- return blink::mojom::WebBluetoothError::SERVICE_NO_LONGER_EXISTS;
+ return blink::mojom::WebBluetoothResult::SERVICE_NO_LONGER_EXISTS;
case CacheQueryOutcome::NO_CHARACTERISTIC:
- return blink::mojom::WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS;
+ return blink::mojom::WebBluetoothResult::
+ CHARACTERISTIC_NO_LONGER_EXISTS;
}
NOTREACHED();
- return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothResult::DEVICE_NO_LONGER_IN_RANGE;
}
device::BluetoothDevice* device = nullptr;
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 655fb3ea730..0b70dec104f 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -15,7 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_blocklist.h"
#include "content/browser/bluetooth/bluetooth_device_chooser_controller.h"
#include "content/browser/bluetooth/bluetooth_metrics.h"
#include "content/browser/bluetooth/frame_connected_bluetooth_devices.h"
@@ -35,99 +35,99 @@ namespace content {
namespace {
-blink::mojom::WebBluetoothError TranslateConnectErrorAndRecord(
+blink::mojom::WebBluetoothResult TranslateConnectErrorAndRecord(
device::BluetoothDevice::ConnectErrorCode error_code) {
switch (error_code) {
case device::BluetoothDevice::ERROR_UNKNOWN:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNKNOWN);
- return blink::mojom::WebBluetoothError::CONNECT_UNKNOWN_ERROR;
+ return blink::mojom::WebBluetoothResult::CONNECT_UNKNOWN_ERROR;
case device::BluetoothDevice::ERROR_INPROGRESS:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::IN_PROGRESS);
- return blink::mojom::WebBluetoothError::CONNECT_ALREADY_IN_PROGRESS;
+ return blink::mojom::WebBluetoothResult::CONNECT_ALREADY_IN_PROGRESS;
case device::BluetoothDevice::ERROR_FAILED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::FAILED);
- return blink::mojom::WebBluetoothError::CONNECT_UNKNOWN_FAILURE;
+ return blink::mojom::WebBluetoothResult::CONNECT_UNKNOWN_FAILURE;
case device::BluetoothDevice::ERROR_AUTH_FAILED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_FAILED);
- return blink::mojom::WebBluetoothError::CONNECT_AUTH_FAILED;
+ return blink::mojom::WebBluetoothResult::CONNECT_AUTH_FAILED;
case device::BluetoothDevice::ERROR_AUTH_CANCELED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_CANCELED);
- return blink::mojom::WebBluetoothError::CONNECT_AUTH_CANCELED;
+ return blink::mojom::WebBluetoothResult::CONNECT_AUTH_CANCELED;
case device::BluetoothDevice::ERROR_AUTH_REJECTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_REJECTED);
- return blink::mojom::WebBluetoothError::CONNECT_AUTH_REJECTED;
+ return blink::mojom::WebBluetoothResult::CONNECT_AUTH_REJECTED;
case device::BluetoothDevice::ERROR_AUTH_TIMEOUT:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_TIMEOUT);
- return blink::mojom::WebBluetoothError::CONNECT_AUTH_TIMEOUT;
+ return blink::mojom::WebBluetoothResult::CONNECT_AUTH_TIMEOUT;
case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNSUPPORTED_DEVICE);
- return blink::mojom::WebBluetoothError::CONNECT_UNSUPPORTED_DEVICE;
+ return blink::mojom::WebBluetoothResult::CONNECT_UNSUPPORTED_DEVICE;
case device::BluetoothDevice::ERROR_ATTRIBUTE_LENGTH_INVALID:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::ATTRIBUTE_LENGTH_INVALID);
- return blink::mojom::WebBluetoothError::CONNECT_ATTRIBUTE_LENGTH_INVALID;
+ return blink::mojom::WebBluetoothResult::CONNECT_ATTRIBUTE_LENGTH_INVALID;
case device::BluetoothDevice::ERROR_CONNECTION_CONGESTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::CONNECTION_CONGESTED);
- return blink::mojom::WebBluetoothError::CONNECT_CONNECTION_CONGESTED;
+ return blink::mojom::WebBluetoothResult::CONNECT_CONNECTION_CONGESTED;
case device::BluetoothDevice::ERROR_INSUFFICIENT_ENCRYPTION:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::INSUFFICIENT_ENCRYPTION);
- return blink::mojom::WebBluetoothError::CONNECT_INSUFFICIENT_ENCRYPTION;
+ return blink::mojom::WebBluetoothResult::CONNECT_INSUFFICIENT_ENCRYPTION;
case device::BluetoothDevice::ERROR_OFFSET_INVALID:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::OFFSET_INVALID);
- return blink::mojom::WebBluetoothError::CONNECT_OFFSET_INVALID;
+ return blink::mojom::WebBluetoothResult::CONNECT_OFFSET_INVALID;
case device::BluetoothDevice::ERROR_READ_NOT_PERMITTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::READ_NOT_PERMITTED);
- return blink::mojom::WebBluetoothError::CONNECT_READ_NOT_PERMITTED;
+ return blink::mojom::WebBluetoothResult::CONNECT_READ_NOT_PERMITTED;
case device::BluetoothDevice::ERROR_REQUEST_NOT_SUPPORTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::REQUEST_NOT_SUPPORTED);
- return blink::mojom::WebBluetoothError::CONNECT_REQUEST_NOT_SUPPORTED;
+ return blink::mojom::WebBluetoothResult::CONNECT_REQUEST_NOT_SUPPORTED;
case device::BluetoothDevice::ERROR_WRITE_NOT_PERMITTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::WRITE_NOT_PERMITTED);
- return blink::mojom::WebBluetoothError::CONNECT_WRITE_NOT_PERMITTED;
+ return blink::mojom::WebBluetoothResult::CONNECT_WRITE_NOT_PERMITTED;
case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES:
NOTREACHED();
- return blink::mojom::WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE;
+ return blink::mojom::WebBluetoothResult::UNTRANSLATED_CONNECT_ERROR_CODE;
}
NOTREACHED();
- return blink::mojom::WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE;
+ return blink::mojom::WebBluetoothResult::UNTRANSLATED_CONNECT_ERROR_CODE;
}
-blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord(
+blink::mojom::WebBluetoothResult TranslateGATTErrorAndRecord(
device::BluetoothRemoteGattService::GattErrorCode error_code,
UMAGATTOperation operation) {
switch (error_code) {
case device::BluetoothRemoteGattService::GATT_ERROR_UNKNOWN:
RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN);
- return blink::mojom::WebBluetoothError::GATT_UNKNOWN_ERROR;
+ return blink::mojom::WebBluetoothResult::GATT_UNKNOWN_ERROR;
case device::BluetoothRemoteGattService::GATT_ERROR_FAILED:
RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED);
- return blink::mojom::WebBluetoothError::GATT_UNKNOWN_FAILURE;
+ return blink::mojom::WebBluetoothResult::GATT_UNKNOWN_FAILURE;
case device::BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::IN_PROGRESS);
- return blink::mojom::WebBluetoothError::GATT_OPERATION_IN_PROGRESS;
+ return blink::mojom::WebBluetoothResult::GATT_OPERATION_IN_PROGRESS;
case device::BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::INVALID_LENGTH);
- return blink::mojom::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH;
+ return blink::mojom::WebBluetoothResult::GATT_INVALID_ATTRIBUTE_LENGTH;
case device::BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_PERMITTED);
- return blink::mojom::WebBluetoothError::GATT_NOT_PERMITTED;
+ return blink::mojom::WebBluetoothResult::GATT_NOT_PERMITTED;
case device::BluetoothRemoteGattService::GATT_ERROR_NOT_AUTHORIZED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_AUTHORIZED);
- return blink::mojom::WebBluetoothError::GATT_NOT_AUTHORIZED;
+ return blink::mojom::WebBluetoothResult::GATT_NOT_AUTHORIZED;
case device::BluetoothRemoteGattService::GATT_ERROR_NOT_PAIRED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_PAIRED);
- return blink::mojom::WebBluetoothError::GATT_NOT_PAIRED;
+ return blink::mojom::WebBluetoothResult::GATT_NOT_PAIRED;
case device::BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_SUPPORTED);
- return blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED;
+ return blink::mojom::WebBluetoothResult::GATT_NOT_SUPPORTED;
}
NOTREACHED();
- return blink::mojom::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE;
+ return blink::mojom::WebBluetoothResult::GATT_UNTRANSLATED_ERROR_CODE;
}
// TODO(ortuno): This should really be a BluetoothDevice method.
@@ -308,10 +308,10 @@ void WebBluetoothServiceImpl::GattCharacteristicValueChanged(
void WebBluetoothServiceImpl::NotifyCharacteristicValueChanged(
const std::string& characteristic_instance_id,
- std::vector<uint8_t> value) {
+ const std::vector<uint8_t>& value) {
if (client_) {
- client_->RemoteCharacteristicValueChanged(
- characteristic_instance_id, mojo::Array<uint8_t>(std::move(value)));
+ client_->RemoteCharacteristicValueChanged(characteristic_instance_id,
+ value);
}
}
@@ -338,7 +338,7 @@ void WebBluetoothServiceImpl::RequestDevice(
RecordRequestDeviceOutcome(
UMARequestDeviceOutcome::BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE);
callback.Run(
- blink::mojom::WebBluetoothError::BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE,
+ blink::mojom::WebBluetoothResult::BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE,
nullptr /* device */);
return;
}
@@ -355,13 +355,13 @@ void WebBluetoothServiceImpl::RemoteServerConnect(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordConnectGATTOutcome(query_result.outcome);
- callback.Run(query_result.GetWebError());
+ callback.Run(query_result.GetWebResult());
return;
}
if (connected_devices_->IsConnectedToDeviceWithId(device_id)) {
VLOG(1) << "Already connected.";
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS);
return;
}
@@ -407,11 +407,20 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServices(
: UMAWebBluetoothFunction::GET_PRIMARY_SERVICES);
RecordGetPrimaryServicesServices(quantity, services_uuid);
+ if (!allowed_devices_map_.IsOriginAllowedToAccessAtLeastOneService(
+ GetOrigin(), device_id)) {
+ callback.Run(
+ blink::mojom::WebBluetoothResult::NOT_ALLOWED_TO_ACCESS_ANY_SERVICE,
+ base::nullopt /* service */);
+ return;
+ }
+
if (services_uuid &&
!allowed_devices_map_.IsOriginAllowedToAccessService(
GetOrigin(), device_id, services_uuid.value())) {
- callback.Run(blink::mojom::WebBluetoothError::NOT_ALLOWED_TO_ACCESS_SERVICE,
- nullptr /* service */);
+ callback.Run(
+ blink::mojom::WebBluetoothResult::NOT_ALLOWED_TO_ACCESS_SERVICE,
+ base::nullopt /* service */);
return;
}
@@ -423,7 +432,7 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServices(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordGetPrimaryServicesOutcome(quantity, query_result.outcome);
- callback.Run(query_result.GetWebError(), nullptr /* service */);
+ callback.Run(query_result.GetWebResult(), base::nullopt /* service */);
return;
}
@@ -444,7 +453,7 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServices(
}
void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
- const mojo::String& service_instance_id,
+ const std::string& service_instance_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
const base::Optional<BluetoothUUID>& characteristics_uuid,
const RemoteServiceGetCharacteristicsCallback& callback) {
@@ -457,12 +466,12 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
RecordGetCharacteristicsCharacteristic(quantity, characteristics_uuid);
if (characteristics_uuid &&
- BluetoothBlacklist::Get().IsExcluded(characteristics_uuid.value())) {
+ BluetoothBlocklist::Get().IsExcluded(characteristics_uuid.value())) {
RecordGetCharacteristicsOutcome(quantity,
- UMAGetCharacteristicOutcome::BLACKLISTED);
+ UMAGetCharacteristicOutcome::BLOCKLISTED);
callback.Run(
- blink::mojom::WebBluetoothError::BLACKLISTED_CHARACTERISTIC_UUID,
- nullptr /* characteristics */);
+ blink::mojom::WebBluetoothResult::BLOCKLISTED_CHARACTERISTIC_UUID,
+ base::nullopt /* characteristics */);
return;
}
@@ -475,7 +484,8 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordGetCharacteristicsOutcome(quantity, query_result.outcome);
- callback.Run(query_result.GetWebError(), nullptr /* characteristics */);
+ callback.Run(query_result.GetWebResult(),
+ base::nullopt /* characteristics */);
return;
}
@@ -485,11 +495,11 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
characteristics_uuid.value())
: query_result.service->GetCharacteristics();
- mojo::Array<blink::mojom::WebBluetoothRemoteGATTCharacteristicPtr>
+ std::vector<blink::mojom::WebBluetoothRemoteGATTCharacteristicPtr>
response_characteristics;
for (device::BluetoothRemoteGattCharacteristic* characteristic :
characteristics) {
- if (BluetoothBlacklist::Get().IsExcluded(characteristic->GetUUID())) {
+ if (BluetoothBlocklist::Get().IsExcluded(characteristic->GetUUID())) {
continue;
}
std::string characteristic_instance_id = characteristic->GetIdentifier();
@@ -515,7 +525,7 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
if (!response_characteristics.empty()) {
RecordGetCharacteristicsOutcome(quantity,
UMAGetCharacteristicOutcome::SUCCESS);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS,
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS,
std::move(response_characteristics));
return;
}
@@ -525,13 +535,13 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
? UMAGetCharacteristicOutcome::NOT_FOUND
: UMAGetCharacteristicOutcome::NO_CHARACTERISTICS);
callback.Run(characteristics_uuid
- ? blink::mojom::WebBluetoothError::CHARACTERISTIC_NOT_FOUND
- : blink::mojom::WebBluetoothError::NO_CHARACTERISTICS_FOUND,
- nullptr /* characteristics */);
+ ? blink::mojom::WebBluetoothResult::CHARACTERISTIC_NOT_FOUND
+ : blink::mojom::WebBluetoothResult::NO_CHARACTERISTICS_FOUND,
+ base::nullopt /* characteristics */);
}
void WebBluetoothServiceImpl::RemoteCharacteristicReadValue(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicReadValueCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
@@ -546,15 +556,15 @@ void WebBluetoothServiceImpl::RemoteCharacteristicReadValue(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordCharacteristicReadValueOutcome(query_result.outcome);
- callback.Run(query_result.GetWebError(), nullptr /* value */);
+ callback.Run(query_result.GetWebResult(), base::nullopt /* value */);
return;
}
- if (BluetoothBlacklist::Get().IsExcludedFromReads(
+ if (BluetoothBlocklist::Get().IsExcludedFromReads(
query_result.characteristic->GetUUID())) {
- RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::BLACKLISTED);
- callback.Run(blink::mojom::WebBluetoothError::BLACKLISTED_READ,
- nullptr /* value */);
+ RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::BLOCKLISTED);
+ callback.Run(blink::mojom::WebBluetoothResult::BLOCKLISTED_READ,
+ base::nullopt /* value */);
return;
}
@@ -566,8 +576,8 @@ void WebBluetoothServiceImpl::RemoteCharacteristicReadValue(
}
void WebBluetoothServiceImpl::RemoteCharacteristicWriteValue(
- const mojo::String& characteristic_instance_id,
- mojo::Array<uint8_t> value,
+ const std::string& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
const RemoteCharacteristicWriteValueCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
@@ -590,27 +600,26 @@ void WebBluetoothServiceImpl::RemoteCharacteristicWriteValue(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordCharacteristicWriteValueOutcome(query_result.outcome);
- callback.Run(query_result.GetWebError());
+ callback.Run(query_result.GetWebResult());
return;
}
- if (BluetoothBlacklist::Get().IsExcludedFromWrites(
+ if (BluetoothBlocklist::Get().IsExcludedFromWrites(
query_result.characteristic->GetUUID())) {
- RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::BLACKLISTED);
- callback.Run(blink::mojom::WebBluetoothError::BLACKLISTED_WRITE);
+ RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::BLOCKLISTED);
+ callback.Run(blink::mojom::WebBluetoothResult::BLOCKLISTED_WRITE);
return;
}
query_result.characteristic->WriteRemoteCharacteristic(
- value.To<std::vector<uint8_t>>(),
- base::Bind(&WebBluetoothServiceImpl::OnWriteValueSuccess,
- weak_ptr_factory_.GetWeakPtr(), callback),
+ value, base::Bind(&WebBluetoothServiceImpl::OnWriteValueSuccess,
+ weak_ptr_factory_.GetWeakPtr(), callback),
base::Bind(&WebBluetoothServiceImpl::OnWriteValueFailed,
weak_ptr_factory_.GetWeakPtr(), callback));
}
void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicStartNotificationsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
@@ -622,7 +631,7 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
iter->second->IsActive()) {
// If the frame has already started notifications and the notifications
// are active we return SUCCESS.
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS);
return;
}
@@ -635,7 +644,7 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordStartNotificationsOutcome(query_result.outcome);
- callback.Run(query_result.GetWebError());
+ callback.Run(query_result.GetWebResult());
return;
}
@@ -644,7 +653,7 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
(device::BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY |
device::BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE);
if (!notify_or_indicate) {
- callback.Run(blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED);
+ callback.Run(blink::mojom::WebBluetoothResult::GATT_NOT_SUPPORTED);
return;
}
@@ -656,7 +665,7 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
}
void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicStopNotificationsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
@@ -717,7 +726,7 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServicesImpl(
services_uuid ? GetPrimaryServicesByUUID(device, services_uuid.value())
: GetPrimaryServices(device);
- mojo::Array<blink::mojom::WebBluetoothRemoteGATTServicePtr> response_services;
+ std::vector<blink::mojom::WebBluetoothRemoteGATTServicePtr> response_services;
for (device::BluetoothRemoteGattService* service : services) {
if (!allowed_devices_map_.IsOriginAllowedToAccessService(
GetOrigin(), device_id, service->GetUUID())) {
@@ -746,7 +755,7 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServicesImpl(
VLOG(1) << "Services found in device.";
RecordGetPrimaryServicesOutcome(quantity,
UMAGetPrimaryServiceOutcome::SUCCESS);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS,
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS,
std::move(response_services));
return;
}
@@ -756,9 +765,9 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServicesImpl(
quantity, services_uuid ? UMAGetPrimaryServiceOutcome::NOT_FOUND
: UMAGetPrimaryServiceOutcome::NO_SERVICES);
callback.Run(services_uuid
- ? blink::mojom::WebBluetoothError::SERVICE_NOT_FOUND
- : blink::mojom::WebBluetoothError::NO_SERVICES_FOUND,
- nullptr /* services */);
+ ? blink::mojom::WebBluetoothResult::SERVICE_NOT_FOUND
+ : blink::mojom::WebBluetoothResult::NO_SERVICES_FOUND,
+ base::nullopt /* services */);
}
void WebBluetoothServiceImpl::OnGetDeviceSuccess(
@@ -772,7 +781,7 @@ void WebBluetoothServiceImpl::OnGetDeviceSuccess(
if (device == nullptr) {
VLOG(1) << "Device " << device_address << " no longer in adapter";
RecordRequestDeviceOutcome(UMARequestDeviceOutcome::CHOSEN_DEVICE_VANISHED);
- callback.Run(blink::mojom::WebBluetoothError::CHOSEN_DEVICE_VANISHED,
+ callback.Run(blink::mojom::WebBluetoothResult::CHOSEN_DEVICE_VANISHED,
nullptr /* device */);
return;
}
@@ -781,35 +790,22 @@ void WebBluetoothServiceImpl::OnGetDeviceSuccess(
allowed_devices_map_.AddDevice(GetOrigin(), device_address, options);
VLOG(1) << "Device: " << device->GetNameForDisplay();
- VLOG(1) << "UUIDs: ";
-
- mojo::Array<mojo::String> filtered_uuids;
- for (const BluetoothUUID& uuid : device->GetUUIDs()) {
- if (allowed_devices_map_.IsOriginAllowedToAccessService(
- GetOrigin(), device_id_for_origin, uuid)) {
- VLOG(1) << "\t Allowed: " << uuid.canonical_value();
- filtered_uuids.push_back(uuid.canonical_value());
- } else {
- VLOG(1) << "\t Not Allowed: " << uuid.canonical_value();
- }
- }
blink::mojom::WebBluetoothDevicePtr device_ptr =
blink::mojom::WebBluetoothDevice::New();
device_ptr->id = device_id_for_origin;
- device_ptr->name = device->GetName() ? mojo::String(device->GetName().value())
- : mojo::String(nullptr);
- device_ptr->uuids = std::move(filtered_uuids);
+ device_ptr->name = device->GetName();
RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS, std::move(device_ptr));
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS,
+ std::move(device_ptr));
}
void WebBluetoothServiceImpl::OnGetDeviceFailed(
const RequestDeviceCallback& callback,
- blink::mojom::WebBluetoothError error) {
+ blink::mojom::WebBluetoothResult result) {
// Errors are recorded by the *device_chooser_controller_.
- callback.Run(error, nullptr /* device */);
+ callback.Run(result, nullptr /* device */);
device_chooser_controller_.reset();
}
@@ -823,7 +819,7 @@ void WebBluetoothServiceImpl::OnCreateGATTConnectionSuccess(
RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS);
connected_devices_->Insert(device_id, std::move(connection));
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS);
}
void WebBluetoothServiceImpl::OnCreateGATTConnectionFailed(
@@ -840,8 +836,7 @@ void WebBluetoothServiceImpl::OnReadValueSuccess(
const std::vector<uint8_t>& value) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::SUCCESS);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS,
- mojo::Array<uint8_t>::From(value));
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS, value);
}
void WebBluetoothServiceImpl::OnReadValueFailed(
@@ -850,14 +845,14 @@ void WebBluetoothServiceImpl::OnReadValueFailed(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
callback.Run(TranslateGATTErrorAndRecord(
error_code, UMAGATTOperation::CHARACTERISTIC_READ),
- nullptr /* value */);
+ base::nullopt /* value */);
}
void WebBluetoothServiceImpl::OnWriteValueSuccess(
const RemoteCharacteristicWriteValueCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS);
}
void WebBluetoothServiceImpl::OnWriteValueFailed(
@@ -879,7 +874,7 @@ void WebBluetoothServiceImpl::OnStartNotifySessionSuccess(
// Saving the BluetoothGattNotifySession keeps notifications active.
characteristic_id_to_notify_session_[characteristic_instance_id] =
std::move(notify_session);
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothResult::SUCCESS);
}
void WebBluetoothServiceImpl::OnStartNotifySessionFailed(
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
index c946d2d057e..7bc0feb7825 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -94,7 +94,7 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
// characteristics that have been returned to the client in the past.
void NotifyCharacteristicValueChanged(
const std::string& characteristic_instance_id,
- std::vector<uint8_t> value);
+ const std::vector<uint8_t>& value);
// WebBluetoothService methods:
void SetClient(
@@ -108,25 +108,25 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
void RemoteServerGetPrimaryServices(
const WebBluetoothDeviceId& device_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
- const base::Optional<device::BluetoothUUID>& service_uuid,
+ const base::Optional<device::BluetoothUUID>& services_uuid,
const RemoteServerGetPrimaryServicesCallback& callback) override;
void RemoteServiceGetCharacteristics(
- const mojo::String& service_instance_id,
+ const std::string& service_instance_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
const base::Optional<device::BluetoothUUID>& characteristics_uuid,
const RemoteServiceGetCharacteristicsCallback& callback) override;
void RemoteCharacteristicReadValue(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicReadValueCallback& callback) override;
void RemoteCharacteristicWriteValue(
- const mojo::String& characteristic_instance_id,
- mojo::Array<uint8_t> value,
+ const std::string& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
const RemoteCharacteristicWriteValueCallback& callback) override;
void RemoteCharacteristicStartNotifications(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicStartNotificationsCallback& callback) override;
void RemoteCharacteristicStopNotifications(
- const mojo::String& characteristic_instance_id,
+ const std::string& characteristic_instance_id,
const RemoteCharacteristicStopNotificationsCallback& callback) override;
void RequestDeviceImpl(
@@ -149,7 +149,7 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
const std::string& device_id);
void OnGetDeviceFailed(const RequestDeviceCallback& callback,
- blink::mojom::WebBluetoothError error);
+ blink::mojom::WebBluetoothResult result);
// Callbacks for BluetoothDevice::CreateGattConnection.
void OnCreateGATTConnectionSuccess(
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index a8d19b0a37c..8b4343161de 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -38,13 +38,16 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/connection_filter.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
-#include "ipc/attachment_broker.h"
-#include "ipc/attachment_broker_privileged.h"
+#include "content/public/common/service_manager_connection.h"
+#include "device/power_monitor/power_monitor_message_broadcaster.h"
#include "mojo/edk/embedder/embedder.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#if defined(OS_MACOSX)
#include "content/browser/mach_broker_mac.h"
@@ -60,29 +63,46 @@ base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>>
g_observers = LAZY_INSTANCE_INITIALIZER;
void NotifyProcessLaunchedAndConnected(const ChildProcessData& data) {
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessLaunchedAndConnected(data));
+ for (auto& observer : g_observers.Get())
+ observer.BrowserChildProcessLaunchedAndConnected(data);
}
void NotifyProcessHostConnected(const ChildProcessData& data) {
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessHostConnected(data));
+ for (auto& observer : g_observers.Get())
+ observer.BrowserChildProcessHostConnected(data);
}
void NotifyProcessHostDisconnected(const ChildProcessData& data) {
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessHostDisconnected(data));
+ for (auto& observer : g_observers.Get())
+ observer.BrowserChildProcessHostDisconnected(data);
}
void NotifyProcessCrashed(const ChildProcessData& data, int exit_code) {
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessCrashed(data, exit_code));
+ for (auto& observer : g_observers.Get())
+ observer.BrowserChildProcessCrashed(data, exit_code);
}
void NotifyProcessKilled(const ChildProcessData& data, int exit_code) {
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessKilled(data, exit_code));
-}
+ for (auto& observer : g_observers.Get())
+ observer.BrowserChildProcessKilled(data, exit_code);
+}
+
+class ConnectionFilterImpl : public ConnectionFilter {
+ public:
+ ConnectionFilterImpl() {}
+
+ private:
+ // ConnectionFilter:
+ bool OnConnect(const service_manager::Identity& remote_identity,
+ service_manager::InterfaceRegistry* registry,
+ service_manager::Connector* connector) override {
+ registry->AddInterface(
+ base::Bind(&device::PowerMonitorMessageBroadcaster::Create));
+ return true;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionFilterImpl);
+};
} // namespace
@@ -143,25 +163,11 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
: data_(process_type),
delegate_(delegate),
child_token_(mojo::edk::GenerateRandomToken()),
- power_monitor_message_broadcaster_(this),
is_channel_connected_(false),
notify_child_disconnected_(false),
weak_factory_(this) {
data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
-#if USE_ATTACHMENT_BROKER
- // Construct the privileged attachment broker early in the life cycle of a
- // child process. This ensures that when a test is being run in one of the
- // single process modes, the global attachment broker is the privileged
- // attachment broker, rather than an unprivileged attachment broker.
-#if defined(OS_MACOSX)
- IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(
- MachBroker::GetInstance());
-#else
- IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
-#endif // defined(OS_MACOSX)
-#endif // USE_ATTACHMENT_BROKER
-
child_process_host_.reset(ChildProcessHost::Create(this));
AddFilter(new TraceMessageFilter(data_.id));
AddFilter(new ProfilerMessageFilter(process_type));
@@ -171,8 +177,6 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
g_child_process_list.Get().push_back(this);
GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
- power_monitor_message_broadcaster_.Init();
-
if (!service_name.empty()) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
child_connection_.reset(new ChildConnection(
@@ -181,6 +185,12 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
base::ThreadTaskRunnerHandle::Get()));
}
+ // May be null during test execution.
+ if (ServiceManagerConnection::GetForProcess()) {
+ ServiceManagerConnection::GetForProcess()->AddConnectionFilter(
+ base::MakeUnique<ConnectionFilterImpl>());
+ }
+
// Create a persistent memory segment for subprocess histograms.
CreateMetricsAllocator();
}
@@ -220,12 +230,8 @@ void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
// If we run base::FieldTrials, we want to pass to their state to the
// child process so that it can act in accordance with each state.
- std::string field_trial_states;
- base::FieldTrialList::AllStatesToString(&field_trial_states);
- if (!field_trial_states.empty()) {
- cmd_line->AppendSwitchASCII(switches::kForceFieldTrials,
- field_trial_states);
- }
+ base::FieldTrialList::CopyFieldTrialStateToFlags(switches::kFieldTrialHandle,
+ cmd_line);
}
void BrowserChildProcessHostImpl::Launch(
@@ -258,11 +264,7 @@ void BrowserChildProcessHostImpl::Launch(
notify_child_disconnected_ = true;
child_process_.reset(new ChildProcessLauncher(
- delegate,
- cmd_line,
- data_.id,
- this,
- child_token_,
+ delegate, cmd_line, data_.id, this, child_token_,
base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
weak_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get()),
@@ -317,7 +319,8 @@ void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
child_process_host_->AddFilter(filter->GetFilter());
}
-shell::InterfaceProvider* BrowserChildProcessHostImpl::GetRemoteInterfaces() {
+service_manager::InterfaceProvider*
+BrowserChildProcessHostImpl::GetRemoteInterfaces() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!child_connection_)
return nullptr;
@@ -477,32 +480,32 @@ void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
base::StringPiece metrics_name;
switch (data_.process_type) {
case PROCESS_TYPE_UTILITY:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "UtilityMetrics";
break;
case PROCESS_TYPE_ZYGOTE:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "ZygoteMetrics";
break;
case PROCESS_TYPE_SANDBOX_HELPER:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "SandboxHelperMetrics";
break;
case PROCESS_TYPE_GPU:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "GpuMetrics";
break;
case PROCESS_TYPE_PPAPI_PLUGIN:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "PpapiPluginMetrics";
break;
case PROCESS_TYPE_PPAPI_BROKER:
- memory_size = 100 << 10; // 100 KiB
+ memory_size = 64 << 10; // 64 KiB
metrics_name = "PpapiBrokerMetrics";
break;
@@ -546,6 +549,9 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() {
const base::Process& process = child_process_->GetProcess();
DCHECK(process.IsValid());
+ if (child_connection_)
+ child_connection_->SetProcessHandle(process.Handle());
+
#if defined(OS_WIN)
// Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
// child process exits. This watcher is stopped once the IPC channel is
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index c10b9adf263..9ac631eb79a 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -12,13 +12,13 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "build/build_config.h"
#include "content/browser/child_process_launcher.h"
-#include "content/browser/power_monitor_message_broadcaster.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/common/child_process_host_delegate.h"
@@ -31,7 +31,7 @@ namespace base {
class CommandLine;
}
-namespace shell {
+namespace service_manager {
class InterfaceProvider;
}
@@ -85,7 +85,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
bool CanShutdown() override;
void OnChildDisconnected() override;
const base::Process& GetProcess() const override;
- shell::InterfaceProvider* GetRemoteInterfaces() override;
+ service_manager::InterfaceProvider* GetRemoteInterfaces() override;
bool OnMessageReceived(const IPC::Message& message) override;
void OnChannelConnected(int32_t peer_pid) override;
void OnChannelError() override;
@@ -157,8 +157,6 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
std::unique_ptr<ChildProcessLauncher> child_process_;
- PowerMonitorMessageBroadcaster power_monitor_message_broadcaster_;
-
#if defined(OS_WIN)
// Watches to see if the child process exits before the IPC channel has
// been connected. Thereafter, its exit is determined by an error on the
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 5b7ba414fed..063b0efaf40 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -33,18 +33,20 @@
#include "content/public/browser/site_instance.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "net/cookies/cookie_store.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/channel_id_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/device/device_service.h"
+#include "services/device/public/cpp/constants.h"
#include "services/file/file_service.h"
-#include "services/file/public/cpp/constants.h"
+#include "services/file/public/interfaces/constants.mojom.h"
#include "services/file/user_id_map.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/connector.h"
-#include "services/shell/public/interfaces/service.mojom.h"
+#include "services/service_manager/public/cpp/connection.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/interfaces/service.mojom.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/fileapi/external_mount_points.h"
@@ -150,9 +152,9 @@ void SetDownloadManager(BrowserContext* context,
class BrowserContextServiceManagerConnectionHolder
: public base::SupportsUserData::Data {
public:
- BrowserContextServiceManagerConnectionHolder(
- std::unique_ptr<shell::Connection> connection,
- shell::mojom::ServiceRequest request)
+ BrowserContextServiceManagerConnectionHolder(
+ std::unique_ptr<service_manager::Connection> connection,
+ service_manager::mojom::ServiceRequest request)
: root_connection_(std::move(connection)),
service_manager_connection_(ServiceManagerConnection::Create(
std::move(request),
@@ -164,7 +166,7 @@ class BrowserContextServiceManagerConnectionHolder
}
private:
- std::unique_ptr<shell::Connection> root_connection_;
+ std::unique_ptr<service_manager::Connection> root_connection_;
std::unique_ptr<ServiceManagerConnection> service_manager_connection_;
DISALLOW_COPY_AND_ASSIGN(BrowserContextServiceManagerConnectionHolder);
@@ -431,16 +433,17 @@ void BrowserContext::Initialize(
ServiceManagerConnection* service_manager_connection =
ServiceManagerConnection::GetForProcess();
- if (service_manager_connection && base::MessageLoop::current()) {
+ if (service_manager_connection && base::ThreadTaskRunnerHandle::IsSet()) {
// NOTE: Many unit tests create a TestBrowserContext without initializing
// Mojo or the global service manager connection.
- shell::mojom::ServicePtr service;
- shell::mojom::ServiceRequest service_request = mojo::GetProxy(&service);
+ service_manager::mojom::ServicePtr service;
+ service_manager::mojom::ServiceRequest service_request =
+ mojo::GetProxy(&service);
- shell::mojom::PIDReceiverPtr pid_receiver;
- shell::Connector::ConnectParams params(
- shell::Identity(kBrowserServiceName, new_id));
+ service_manager::mojom::PIDReceiverPtr pid_receiver;
+ service_manager::Connector::ConnectParams params(
+ service_manager::Identity(mojom::kBrowserServiceName, new_id));
params.set_client_process_connection(std::move(service),
mojo::GetProxy(&pid_receiver));
pid_receiver->SetPID(base::GetCurrentProcId());
@@ -456,6 +459,13 @@ void BrowserContext::Initialize(
connection->Start();
// New embedded service factories should be added to |connection| here.
+ // TODO(blundell): Does this belong as a global service rather than per
+ // BrowserContext?
+ ServiceInfo info;
+ info.factory =
+ base::Bind(&device::CreateDeviceService,
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE));
+ connection->AddEmbeddedService(device::kDeviceServiceName, info);
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMojoLocalStorage)) {
@@ -464,7 +474,7 @@ void BrowserContext::Initialize(
base::Bind(&file::CreateFileService,
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
BrowserThread::GetTaskRunnerForThread(BrowserThread::DB));
- connection->AddEmbeddedService(file::kFileServiceName, info);
+ connection->AddEmbeddedService(file::mojom::kServiceName, info);
}
}
}
@@ -489,7 +499,7 @@ BrowserContext* BrowserContext::GetBrowserContextForServiceUserId(
}
// static
-shell::Connector* BrowserContext::GetConnectorFor(
+service_manager::Connector* BrowserContext::GetConnectorFor(
BrowserContext* browser_context) {
ServiceManagerConnection* connection =
GetServiceManagerConnectionFor(browser_context);
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 325b85d3ec2..5a5633d9ce8 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -16,6 +16,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/memory_coordinator_proxy.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
@@ -36,6 +37,7 @@
#include "base/trace_event/memory_dump_manager.h"
#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/browser/trace_config_file.h"
#include "components/tracing/common/process_metrics_memory_dump_provider.h"
#include "components/tracing/common/trace_to_console.h"
@@ -52,10 +54,12 @@
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
+#include "content/browser/gpu/shader_disk_cache.h"
#include "content/browser/histogram_synchronizer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader_delegate_impl.h"
#include "content/browser/media/media_internals.h"
+#include "content/browser/memory/memory_coordinator.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"
@@ -66,7 +70,6 @@
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/public/browser/browser_main_parts.h"
@@ -75,6 +78,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/result_codes.h"
@@ -88,7 +92,8 @@
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/ssl/ssl_config_service.h"
-#include "services/shell/runner/common/client_util.h"
+#include "ppapi/features/features.h"
+#include "services/service_manager/runner/common/client_util.h"
#include "skia/ext/event_tracer_impl.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "sql/sql_memory_dump_provider.h"
@@ -116,6 +121,8 @@
#include "content/public/browser/screen_orientation_provider.h"
#include "gpu/ipc/client/android/in_process_surface_texture_manager.h"
#include "media/base/android/media_client_android.h"
+#include "ui/android/screen_android.h"
+#include "ui/display/screen.h"
#include "ui/gl/gl_surface.h"
#endif
@@ -177,7 +184,7 @@
#include "content/browser/plugin_service_impl.h"
#endif
-#if defined(ENABLE_MOJO_CDM) && defined(ENABLE_PEPPER_CDMS)
+#if defined(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_PEPPER_CDMS)
#include "content/browser/media/cdm_service_impl.h"
#endif
@@ -345,12 +352,12 @@ MSVC_ENABLE_OPTIMIZE();
#if defined(OS_WIN)
// Creates a memory pressure monitor using automatic thresholds, or those
// specified on the command-line. Ownership is passed to the caller.
-base::win::MemoryPressureMonitor* CreateWinMemoryPressureMonitor(
- const base::CommandLine& parsed_command_line) {
- std::vector<std::string> thresholds = base::SplitString(
- parsed_command_line.GetSwitchValueASCII(
- switches::kMemoryPressureThresholdsMb),
- ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+std::unique_ptr<base::win::MemoryPressureMonitor>
+CreateWinMemoryPressureMonitor(const base::CommandLine& parsed_command_line) {
+ std::vector<std::string> thresholds =
+ base::SplitString(parsed_command_line.GetSwitchValueASCII(
+ switches::kMemoryPressureThresholdsMb),
+ ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
int moderate_threshold_mb = 0;
int critical_threshold_mb = 0;
@@ -359,12 +366,12 @@ base::win::MemoryPressureMonitor* CreateWinMemoryPressureMonitor(
base::StringToInt(thresholds[1], &critical_threshold_mb) &&
moderate_threshold_mb >= critical_threshold_mb &&
critical_threshold_mb >= 0) {
- return new base::win::MemoryPressureMonitor(moderate_threshold_mb,
- critical_threshold_mb);
+ return base::MakeUnique<base::win::MemoryPressureMonitor>(
+ moderate_threshold_mb, critical_threshold_mb);
}
// In absence of valid switches use the automatic defaults.
- return new base::win::MemoryPressureMonitor();
+ return base::MakeUnique<base::win::MemoryPressureMonitor>();
}
#endif // defined(OS_WIN)
@@ -630,7 +637,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
// in-process Android WebView. crbug.com/503724 tracks proper fix.
if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
base::DiscardableMemoryAllocator::SetInstance(
- HostDiscardableSharedMemoryManager::current());
+ discardable_memory::DiscardableSharedMemoryManager::current());
}
if (parts_)
@@ -745,19 +752,10 @@ int BrowserMainLoop::PreCreateThreads() {
command_line->GetSwitchValueASCII(switches::kEnableFeatures),
command_line->GetSwitchValueASCII(switches::kDisableFeatures));
- // TODO(chrisha): Abstract away this construction mess to a helper function,
- // once MemoryPressureMonitor is made a concrete class.
-#if defined(OS_CHROMEOS)
- if (chromeos::switches::MemoryPressureHandlingEnabled()) {
- memory_pressure_monitor_.reset(new base::chromeos::MemoryPressureMonitor(
- chromeos::switches::GetMemoryPressureThresholds()));
- }
-#elif defined(OS_MACOSX)
- memory_pressure_monitor_.reset(new base::mac::MemoryPressureMonitor());
-#elif defined(OS_WIN)
- memory_pressure_monitor_.reset(CreateWinMemoryPressureMonitor(
- parsed_command_line_));
-#endif
+ InitializeMemoryManagementComponent();
+
+ if (base::FeatureList::IsEnabled(features::kMemoryCoordinator))
+ MemoryCoordinator::GetInstance()->Start();
#if defined(ENABLE_PLUGINS)
// Prior to any processing happening on the IO thread, we create the
@@ -770,7 +768,7 @@ int BrowserMainLoop::PreCreateThreads() {
}
#endif
-#if defined(ENABLE_MOJO_CDM) && defined(ENABLE_PEPPER_CDMS)
+#if defined(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_PEPPER_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.
@@ -957,6 +955,11 @@ int BrowserMainLoop::CreateThreads() {
}
int BrowserMainLoop::PreMainMessageLoopRun() {
+#if defined(OS_ANDROID)
+ // Let screen instance be overridable by parts.
+ ui::SetScreenAndroid();
+#endif
+
if (parts_) {
TRACE_EVENT0("startup",
"BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
@@ -1065,7 +1068,7 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
device_monitor_mac_.reset();
#endif
- // Shutdown Mojo shell and IPC.
+ // Shutdown the Service Manager and IPC.
service_manager_context_.reset();
mojo_ipc_support_.reset();
@@ -1204,13 +1207,13 @@ void BrowserMainLoop::InitializeMainThread() {
int BrowserMainLoop::BrowserThreadsStarted() {
TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted");
- // Bring up Mojo IPC and shell as early as possible. Initializaing mojo
- // requires the IO thread to have been initialized first. So this cannot
- // happen any earlier than this.
+ // Bring up Mojo IPC and the embedded Service Manager as early as possible.
+ // Initializaing mojo requires the IO thread to have been initialized first,
+ // so this cannot happen any earlier than now.
InitializeMojo();
#if defined(USE_AURA)
- if (shell::ShellIsRemote()) {
+ if (service_manager::ServiceManagerIsRemote()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kIsRunningInMash);
}
@@ -1232,6 +1235,13 @@ int BrowserMainLoop::BrowserThreadsStarted() {
}
#endif
+ // Initialize the GPU shader cache. This needs to be initialized before
+ // BrowserGpuChannelHostFactory below, since that depends on an initialized
+ // ShaderCacheFactory.
+ ShaderCacheFactory::InitInstance(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
+
bool always_uses_gpu = true;
bool established_gpu_channel = false;
#if defined(OS_ANDROID)
@@ -1247,7 +1257,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
established_gpu_channel = true;
if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor() ||
parsed_command_line_.HasSwitch(switches::kDisableGpuEarlyInit) ||
- shell::ShellIsRemote()) {
+ service_manager::ServiceManagerIsRemote()) {
established_gpu_channel = always_uses_gpu = false;
}
gpu::GpuChannelEstablishFactory* factory =
@@ -1287,7 +1297,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
{
TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:MidiManager");
- midi_manager_.reset(media::midi::MidiManager::Create());
+ midi_manager_.reset(midi::MidiManager::Create());
}
#if defined(OS_WIN)
@@ -1299,11 +1309,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
device_monitor_mac_.reset(new media::DeviceMonitorMac());
#endif
-#if defined(OS_WIN)
- UMA_HISTOGRAM_BOOLEAN("Windows.Win32kRendererLockdown",
- IsWin32kRendererLockdownEnabled());
-#endif
-
// RDH needs the IO thread to be created
{
TRACE_EVENT0("startup",
@@ -1373,7 +1378,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// ChildProcess instance which is created by the renderer thread.
if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
!established_gpu_channel && always_uses_gpu && !UsingInProcessGpu() &&
- !shell::ShellIsRemote()) {
+ !service_manager::ServiceManagerIsRemote()) {
TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
TRACE_EVENT_SCOPE_THREAD);
BrowserThread::PostTask(
@@ -1400,6 +1405,45 @@ bool BrowserMainLoop::UsingInProcessGpu() const {
parsed_command_line_.HasSwitch(switches::kInProcessGPU);
}
+void BrowserMainLoop::InitializeMemoryManagementComponent() {
+ // TODO(chrisha): Abstract away this construction mess to a helper function,
+ // once MemoryPressureMonitor is made a concrete class.
+#if defined(OS_CHROMEOS)
+ if (chromeos::switches::MemoryPressureHandlingEnabled()) {
+ memory_pressure_monitor_ =
+ base::MakeUnique<base::chromeos::MemoryPressureMonitor>(
+ chromeos::switches::GetMemoryPressureThresholds());
+ }
+#elif defined(OS_MACOSX)
+ memory_pressure_monitor_ =
+ base::MakeUnique<base::mac::MemoryPressureMonitor>();
+#elif defined(OS_WIN)
+ memory_pressure_monitor_ =
+ CreateWinMemoryPressureMonitor(parsed_command_line_);
+#endif
+
+ if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
+ // Disable MemoryPressureListener when memory coordinator is enabled.
+ base::MemoryPressureListener::SetNotificationsSuppressed(true);
+ // base::Unretained is safe because the lifetime of MemoryCoordinator is
+ // tied to the lifetime of the browser process.
+ base::MemoryCoordinatorProxy::GetInstance()->
+ SetGetCurrentMemoryStateCallback(base::Bind(
+ &MemoryCoordinator::GetCurrentMemoryState,
+ base::Unretained(MemoryCoordinator::GetInstance())));
+ base::MemoryCoordinatorProxy::GetInstance()->
+ SetSetCurrentMemoryStateForTestingCallback(base::Bind(
+ &MemoryCoordinator::SetCurrentMemoryStateForTesting,
+ base::Unretained(MemoryCoordinator::GetInstance())));
+
+ if (memory_pressure_monitor_) {
+ memory_pressure_monitor_->SetDispatchCallback(
+ base::Bind(&MemoryCoordinator::RecordMemoryPressure,
+ base::Unretained(MemoryCoordinator::GetInstance())));
+ }
+ }
+}
+
bool BrowserMainLoop::InitializeToolkit() {
TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit");
@@ -1467,8 +1511,7 @@ void BrowserMainLoop::InitializeMojo() {
}
mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
- BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
- ->task_runner()));
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
service_manager_context_.reset(new ServiceManagerContext);
#if defined(OS_MACOSX)
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index c0217e723fd..1464de7ced9 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -49,10 +49,11 @@ class UserInputMonitor;
#if defined(OS_MACOSX)
class DeviceMonitorMac;
#endif
+} // namespace media
+
namespace midi {
class MidiManager;
} // namespace midi
-} // namespace media
namespace mojo {
namespace edk {
@@ -143,7 +144,7 @@ class CONTENT_EXPORT BrowserMainLoop {
device::TimeZoneMonitor* time_zone_monitor() const {
return time_zone_monitor_.get();
}
- media::midi::MidiManager* midi_manager() const { return midi_manager_.get(); }
+ midi::MidiManager* midi_manager() const { return midi_manager_.get(); }
base::Thread* indexed_db_thread() const { return indexed_db_thread_.get(); }
bool is_tracing_startup_for_duration() const {
@@ -189,6 +190,8 @@ class CONTENT_EXPORT BrowserMainLoop {
void CreateAudioManager();
bool UsingInProcessGpu() const;
+ void InitializeMemoryManagementComponent();
+
// Quick reference for initialization order:
// Constructor
// Init()
@@ -287,7 +290,7 @@ class CONTENT_EXPORT BrowserMainLoop {
std::unique_ptr<base::Thread> audio_thread_;
media::ScopedAudioManagerPtr audio_manager_;
- std::unique_ptr<media::midi::MidiManager> midi_manager_;
+ std::unique_ptr<midi::MidiManager> midi_manager_;
#if defined(OS_WIN)
std::unique_ptr<media::SystemMessageWindowWin> system_message_window_;
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index b14ee36b8f7..2116cc260ed 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -87,20 +87,6 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
base::debug::WaitForDebugger(60, true);
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- // When "Extend support of advanced text services to all programs"
- // (a.k.a. Cicero Unaware Application Support; CUAS) is enabled on
- // Windows XP and handwriting modules shipped with Office 2003 are
- // installed, "penjpn.dll" and "skchui.dll" will be loaded and then
- // crash unless a user installs Office 2003 SP3. To prevent these
- // modules from being loaded, disable TSF entirely. crbug.com/160914.
- // TODO(yukawa): Add a high-level wrapper for this instead of calling
- // Win32 API here directly.
- ImmDisableTextFrameService(static_cast<DWORD>(-1));
- }
-#endif // OS_WIN
-
base::StatisticsRecorder::Initialize();
notification_service_.reset(new NotificationServiceImpl);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index 16a75a190b2..76e2446effb 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -116,10 +116,6 @@ void BrowserPluginEmbedder::DidSendScreenRects() {
base::Bind(&BrowserPluginEmbedder::DidSendScreenRectsCallback));
}
-bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) {
- return OnMessageReceived(message, nullptr);
-}
-
bool BrowserPluginEmbedder::OnMessageReceived(
const IPC::Message& message,
RenderFrameHost* render_frame_host) {
@@ -127,8 +123,6 @@ bool BrowserPluginEmbedder::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginEmbedder, message,
render_frame_host)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Attach, OnAttach)
- IPC_MESSAGE_HANDLER_GENERIC(DragHostMsg_UpdateDragCursor,
- OnUpdateDragCursor(&handled));
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -156,8 +150,8 @@ void BrowserPluginEmbedder::SystemDragEnded() {
ClearGuestDragStateIfApplicable();
}
-void BrowserPluginEmbedder::OnUpdateDragCursor(bool* handled) {
- *handled = !!guest_dragging_over_;
+bool BrowserPluginEmbedder::OnUpdateDragCursor() {
+ return !!guest_dragging_over_;
}
void BrowserPluginEmbedder::OnAttach(
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
index 71f97853fda..5e4026c978a 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -26,7 +26,6 @@ namespace content {
class BrowserPluginGuest;
class BrowserPluginGuestManager;
-class RenderWidgetHostImpl;
struct NativeWebKeyboardEvent;
class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
@@ -39,7 +38,6 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
void DidSendScreenRects();
// WebContentsObserver implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
bool OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host) override;
@@ -68,6 +66,11 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
// operation, if there's any.
void SystemDragEnded();
+ // The page wants to update the mouse cursor during a drag & drop
+ // operation. This update will be suppressed if the cursor is dragging over a
+ // guest.
+ bool OnUpdateDragCursor();
+
// Used to handle special keyboard events.
bool HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
@@ -118,7 +121,6 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
void OnAttach(RenderFrameHost* render_frame_host,
int instance_id,
const BrowserPluginHostMsg_Attach_Params& params);
- void OnUpdateDragCursor(bool* handled);
// Used to correctly update the cursor when dragging over a guest, and to
// handle a race condition when dropping onto the guest that started the drag
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 2dc039f7bce..d4d4f14d881 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
@@ -48,6 +49,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/drop_data.h"
+#include "ui/events/blink/web_input_event_traits.h"
#include "ui/gfx/geometry/size_conversions.h"
#if defined(OS_MACOSX)
@@ -124,20 +126,31 @@ int BrowserPluginGuest::GetGuestProxyRoutingID() {
if (guest_proxy_routing_id_ != MSG_ROUTING_NONE)
return guest_proxy_routing_id_;
- // Create a RenderFrameProxyHost for the guest in the embedder renderer
- // process, so that the embedder can access the guest's window object.
- // On reattachment, we can reuse the same RenderFrameProxyHost because
- // the embedder process will always be the same even if the embedder
- // WebContents changes.
+ // In order to enable the embedder to post messages to the
+ // guest, we need to create a RenderFrameProxyHost in root node of guest
+ // WebContents' frame tree (i.e., create a RenderFrameProxy in the embedder
+ // process which can be used by the embedder to post messages to the guest).
+ // The creation of RFPH for the reverse path, which enables the guest to post
+ // messages to the embedder, will be postponed to when the embedder posts its
+ // first message to the guest.
//
// TODO(fsamuel): Make sure this works for transferring guests across
// owners in different processes. We probably need to clear the
// |guest_proxy_routing_id_| and perform any necessary cleanup on Detach
// to enable this.
- SiteInstance* owner_site_instance = owner_web_contents_->GetSiteInstance();
- int proxy_routing_id =
- GetWebContents()->GetFrameTree()->root()->render_manager()->
- CreateRenderFrameProxy(owner_site_instance);
+ //
+ // TODO(ekaramad): If the guest is embedded inside a cross-process <iframe>
+ // (e.g., <embed>-ed PDF), the reverse proxy will not be created and the
+ // posted message's source attribute will be null which in turn breaks the
+ // two-way messaging between the guest and the embedder. We should either
+ // create a RenderFrameProxyHost for the reverse path, or implement
+ // MimeHandlerViewGuest using OOPIF (https://crbug.com/659750).
+ SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
+ int proxy_routing_id = GetWebContents()
+ ->GetFrameTree()
+ ->root()
+ ->render_manager()
+ ->CreateRenderFrameProxy(owner_site_instance);
guest_proxy_routing_id_ = RenderFrameProxyHost::FromID(
owner_site_instance->GetProcess()->GetID(), proxy_routing_id)
->GetRenderViewHost()->GetRoutingID();
@@ -168,6 +181,11 @@ void BrowserPluginGuest::WillDestroy() {
attached_ = false;
}
+RenderWidgetHostImpl* BrowserPluginGuest::GetOwnerRenderWidgetHost() const {
+ return static_cast<RenderWidgetHostImpl*>(
+ delegate_->GetOwnerRenderWidgetHost());
+}
+
void BrowserPluginGuest::Init() {
if (initialized_)
return;
@@ -216,7 +234,7 @@ void BrowserPluginGuest::SetTooltipText(const base::string16& tooltip_text) {
return;
current_tooltip_text_ = tooltip_text;
- SendMessageToEmbedder(new BrowserPluginMsg_SetTooltipText(
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetTooltipText>(
browser_plugin_instance_id_, tooltip_text));
}
@@ -239,12 +257,11 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
const IPC::Message& message) {
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
+
// Until the guest is attached, it should not be handling input events.
if (attached() && rwhv &&
- rwhv->OnMessageReceivedFromEmbedder(
- message,
- RenderWidgetHostImpl::From(
- embedder_web_contents()->GetRenderViewHost()->GetWidget()))) {
+ rwhv->OnMessageReceivedFromEmbedder(message,
+ GetOwnerRenderWidgetHost())) {
return true;
}
@@ -372,9 +389,9 @@ bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
}
RenderWidgetHostView* BrowserPluginGuest::GetOwnerRenderWidgetHostView() {
- if (!owner_web_contents_)
- return nullptr;
- return owner_web_contents_->GetRenderWidgetHostView();
+ if (RenderWidgetHostImpl* owner = GetOwnerRenderWidgetHost())
+ return owner->GetView();
+ return nullptr;
}
void BrowserPluginGuest::UpdateVisibility() {
@@ -392,8 +409,8 @@ void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
}
void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
- SendMessageToEmbedder(
- new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow));
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetMouseLock>(
+ browser_plugin_instance_id(), allow));
}
void BrowserPluginGuest::SetChildFrameSurface(
@@ -402,7 +419,7 @@ void BrowserPluginGuest::SetChildFrameSurface(
float scale_factor,
const cc::SurfaceSequence& sequence) {
has_attached_since_surface_set_ = false;
- SendMessageToEmbedder(new BrowserPluginMsg_SetChildFrameSurface(
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetChildFrameSurface>(
browser_plugin_instance_id(), surface_id, frame_size, scale_factor,
sequence));
}
@@ -446,8 +463,8 @@ void BrowserPluginGuest::ResendEventToEmbedder(
return;
DCHECK(browser_plugin_instance_id_);
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- embedder_web_contents()->GetMainFrame()->GetView());
+ RenderWidgetHostViewBase* view =
+ static_cast<RenderWidgetHostViewBase*>(GetOwnerRenderWidgetHostView());
gfx::Vector2d offset_from_embedder = guest_window_rect_.OffsetFromOrigin();
if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
@@ -458,7 +475,10 @@ void BrowserPluginGuest::ResendEventToEmbedder(
// Mark the resend source with the browser plugin's instance id, so the
// correct browser_plugin will know to ignore the event.
resent_gesture_event.resendingPluginId = browser_plugin_instance_id_;
- view->ProcessGestureEvent(resent_gesture_event, ui::LatencyInfo());
+ ui::LatencyInfo latency_info =
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
+ resent_gesture_event);
+ view->ProcessGestureEvent(resent_gesture_event, latency_info);
} else if (event.type == blink::WebInputEvent::MouseWheel) {
blink::WebMouseWheelEvent resent_wheel_event;
memcpy(&resent_wheel_event, &event, sizeof(blink::WebMouseWheelEvent));
@@ -467,7 +487,7 @@ void BrowserPluginGuest::ResendEventToEmbedder(
resent_wheel_event.resendingPluginId = browser_plugin_instance_id_;
// TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
// https://crbug.com/613628
- ui::LatencyInfo latency_info;
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
view->ProcessMouseWheelEvent(resent_wheel_event, latency_info);
} else {
NOTIMPLEMENTED();
@@ -488,7 +508,8 @@ gfx::Point BrowserPluginGuest::GetScreenCoordinates(
return screen_pos;
}
-void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
+void BrowserPluginGuest::SendMessageToEmbedder(
+ std::unique_ptr<IPC::Message> msg) {
// During tests, attache() may be true when there is no owner_web_contents_;
// in this case just queue any messages we receive.
if (!attached() || !owner_web_contents_) {
@@ -497,16 +518,26 @@ void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
// As a result, we must save all these IPCs until attachment and then
// forward them so that the embedder gets a chance to see and process
// the load events.
- pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
+ pending_messages_.push_back(std::move(msg));
return;
}
- owner_web_contents_->Send(msg);
-}
-void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
- int screen_x, int screen_y, blink::WebDragOperation operation) {
- web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
- screen_x, screen_y, operation);
+ // If the guest is inside a cross-process frame, it is possible to get here
+ // after the owner frame is detached. Then, the owner RenderWidgetHost will
+ // be null and the message is dropped.
+ if (auto* rwh = GetOwnerRenderWidgetHost())
+ rwh->Send(msg.release());
+}
+
+void BrowserPluginGuest::DragSourceEndedAt(int client_x,
+ int client_y,
+ int screen_x,
+ int screen_y,
+ blink::WebDragOperation operation) {
+ web_contents()->GetRenderViewHost()->GetWidget()->DragSourceEndedAt(
+ gfx::Point(client_x, client_y),
+ gfx::Point(screen_x, screen_y),
+ operation);
seen_embedder_drag_source_ended_at_ = true;
EndSystemDragIfApplicable();
}
@@ -535,7 +566,7 @@ void BrowserPluginGuest::EndSystemDragIfApplicable() {
seen_embedder_drag_source_ended_at_ && seen_embedder_system_drag_ended_) {
RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
GetWebContents()->GetRenderViewHost());
- guest_rvh->DragSourceSystemDragEnded();
+ guest_rvh->GetWidget()->DragSourceSystemDragEnded();
last_drag_status_ = blink::WebDragStatusUnknown;
seen_embedder_system_drag_ended_ = false;
seen_embedder_drag_source_ended_at_ = false;
@@ -551,12 +582,12 @@ void BrowserPluginGuest::EmbedderSystemDragEnded() {
// TODO(wjmaclean): Replace this approach with ones based on std::function
// as in https://codereview.chromium.org/1404353004/ once all Chrome platforms
// support this. https://crbug.com/544212
-IPC::Message* BrowserPluginGuest::UpdateInstanceIdIfNecessary(
- IPC::Message* msg) const {
- DCHECK(msg);
+std::unique_ptr<IPC::Message> BrowserPluginGuest::UpdateInstanceIdIfNecessary(
+ std::unique_ptr<IPC::Message> msg) const {
+ DCHECK(msg.get());
int msg_browser_plugin_instance_id = browser_plugin::kInstanceIDNone;
- base::PickleIterator iter(*msg);
+ base::PickleIterator iter(*msg.get());
if (!iter.ReadInt(&msg_browser_plugin_instance_id) ||
msg_browser_plugin_instance_id != browser_plugin::kInstanceIDNone) {
return msg;
@@ -584,8 +615,7 @@ IPC::Message* BrowserPluginGuest::UpdateInstanceIdIfNecessary(
CHECK(write_success)
<< "Unexpected failure writing remaining IPC::Message payload.";
- delete msg;
- return new_msg.release();
+ return new_msg;
}
void BrowserPluginGuest::SendQueuedMessages() {
@@ -593,10 +623,10 @@ void BrowserPluginGuest::SendQueuedMessages() {
return;
while (!pending_messages_.empty()) {
- linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
+ std::unique_ptr<IPC::Message> message_ptr =
+ std::move(pending_messages_.front());
pending_messages_.pop_front();
- SendMessageToEmbedder(
- UpdateInstanceIdIfNecessary(message_ptr.release()));
+ SendMessageToEmbedder(UpdateInstanceIdIfNecessary(std::move(message_ptr)));
}
}
@@ -635,14 +665,22 @@ void BrowserPluginGuest::RenderViewReady() {
Send(new InputMsg_SetFocus(routing_id(), focused_));
UpdateVisibility();
+ // In case we've created a new guest render process after a crash, let the
+ // associated BrowserPlugin know. We only need to send this if we're attached,
+ // as guest_crashed_ is cleared automatically on attach anyways.
+ if (attached()) {
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_GuestReady>(
+ browser_plugin_instance_id()));
+ }
+
RenderWidgetHostImpl::From(rvh->GetWidget())
->set_hung_renderer_delay(
base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
}
void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
- SendMessageToEmbedder(
- new BrowserPluginMsg_GuestGone(browser_plugin_instance_id()));
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_GuestGone>(
+ browser_plugin_instance_id()));
switch (status) {
#if defined(OS_CHROMEOS)
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
@@ -808,28 +846,31 @@ void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
RenderViewHost* host = GetWebContents()->GetRenderViewHost();
auto* embedder = owner_web_contents_->GetBrowserPluginEmbedder();
DropData filtered_data(drop_data);
- host->FilterDropData(&filtered_data);
+ // TODO(paulmeyer): This will need to target the correct specific
+ // RenderWidgetHost to work with OOPIFs. See crbug.com/647249.
+ RenderWidgetHost* widget = host->GetWidget();
+ widget->FilterDropData(&filtered_data);
switch (drag_status) {
case blink::WebDragStatusEnter:
- host->DragTargetDragEnter(filtered_data, location, location, mask,
- drop_data.key_modifiers);
+ widget->DragTargetDragEnter(filtered_data, location, location, mask,
+ drop_data.key_modifiers);
// Only track the URL being dragged over the guest if the link isn't
// coming from the guest.
if (!embedder->DragEnteredGuest(this))
ignore_dragged_url_ = false;
break;
case blink::WebDragStatusOver:
- host->DragTargetDragOver(location, location, mask,
- drop_data.key_modifiers);
+ widget->DragTargetDragOver(location, location, mask,
+ drop_data.key_modifiers);
break;
case blink::WebDragStatusLeave:
embedder->DragLeftGuest(this);
- host->DragTargetDragLeave();
+ widget->DragTargetDragLeave();
ignore_dragged_url_ = true;
break;
case blink::WebDragStatusDrop:
- host->DragTargetDrop(filtered_data, location, location,
- drop_data.key_modifiers);
+ widget->DragTargetDrop(filtered_data, location, location,
+ drop_data.key_modifiers);
if (!ignore_dragged_url_ && filtered_data.url.is_valid())
delegate_->DidDropLink(filtered_data.url);
@@ -943,8 +984,8 @@ void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
}
void BrowserPluginGuest::OnUnlockMouse() {
- SendMessageToEmbedder(
- new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false));
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetMouseLock>(
+ browser_plugin_instance_id(), false));
}
void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
@@ -966,7 +1007,7 @@ void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id,
void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
SendMessageToEmbedder(
- new BrowserPluginMsg_ShouldAcceptTouchEvents(
+ base::MakeUnique<BrowserPluginMsg_ShouldAcceptTouchEvents>(
browser_plugin_instance_id(), accept));
}
@@ -995,8 +1036,8 @@ void BrowserPluginGuest::OnShowWidget(int route_id,
}
void BrowserPluginGuest::OnTakeFocus(bool reverse) {
- SendMessageToEmbedder(
- new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse));
+ SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_AdvanceFocus>(
+ browser_plugin_instance_id(), reverse));
}
void BrowserPluginGuest::OnTextInputStateChanged(const TextInputState& params) {
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index b99654e3bc7..e621ebaac52 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -21,11 +21,11 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <queue>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -37,9 +37,9 @@
#include "content/public/browser/web_contents_observer.h"
#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/WebInputEvent.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/geometry/rect.h"
@@ -65,6 +65,7 @@ namespace content {
class BrowserPluginGuestManager;
class RenderViewHostImpl;
class RenderWidgetHost;
+class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class SiteInstance;
@@ -202,7 +203,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Helper to send messages to embedder. If this guest is not yet attached,
// then IPCs will be queued until attachment.
- void SendMessageToEmbedder(IPC::Message* msg);
+ void SendMessageToEmbedder(std::unique_ptr<IPC::Message> msg);
// Returns whether the guest is attached to an embedder.
bool attached() const { return attached_; }
@@ -279,6 +280,9 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
private:
class EmbedderVisibilityObserver;
+ // The RenderWidgetHostImpl corresponding to the owner frame of BrowserPlugin.
+ RenderWidgetHostImpl* GetOwnerRenderWidgetHost() const;
+
void InitInternal(const BrowserPluginHostMsg_Attach_Params& params,
WebContentsImpl* owner_web_contents);
@@ -381,7 +385,8 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// the input was created with browser_plugin::kInstanceIdNone, else it returns
// the input message unmodified. If no current browser_plugin_instance_id()
// is set, or anything goes wrong, the input message is returned.
- IPC::Message* UpdateInstanceIdIfNecessary(IPC::Message* msg) const;
+ std::unique_ptr<IPC::Message> UpdateInstanceIdIfNecessary(
+ std::unique_ptr<IPC::Message> msg) const;
// Forwards all messages from the |pending_messages_| queue to the embedder.
void SendQueuedMessages();
@@ -447,7 +452,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// This is a queue of messages that are destined to be sent to the embedder
// once the guest is attached to a particular embedder.
- std::deque<linked_ptr<IPC::Message> > pending_messages_;
+ std::deque<std::unique_ptr<IPC::Message>> pending_messages_;
BrowserPluginGuestDelegate* const delegate_;
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index a3a33bdea5e..18eff7c8672 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -185,6 +185,16 @@ void BrowserThreadImpl::FlushThreadPoolHelperForTesting() {
void BrowserThreadImpl::Init() {
BrowserThreadGlobals& globals = g_globals.Get();
+ if (BrowserThread::CurrentlyOn(BrowserThread::DB) ||
+ BrowserThread::CurrentlyOn(BrowserThread::FILE) ||
+ BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING) ||
+ BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER) ||
+ BrowserThread::CurrentlyOn(BrowserThread::CACHE)) {
+ base::MessageLoop* message_loop = base::MessageLoop::current();
+ message_loop->DisallowNesting();
+ message_loop->DisallowTaskObservers();
+ }
+
using base::subtle::AtomicWord;
AtomicWord* storage =
reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
@@ -561,20 +571,6 @@ BrowserThread::GetTaskRunnerForThread(ID identifier) {
return g_task_runners.Get().proxies[identifier];
}
-// static
-base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
- if (g_globals == nullptr)
- return nullptr;
-
- BrowserThreadGlobals& globals = g_globals.Get();
- base::AutoLock lock(globals.lock);
- base::Thread* thread = globals.threads[identifier];
- DCHECK(thread);
- base::MessageLoop* loop = thread->message_loop();
- return loop;
-}
-
-// static
void BrowserThread::SetDelegate(ID identifier,
BrowserThreadDelegate* delegate) {
using base::subtle::AtomicWord;
diff --git a/chromium/content/browser/browser_thread_impl.h b/chromium/content/browser/browser_thread_impl.h
index e86f4ec907a..29081ebbf22 100644
--- a/chromium/content/browser/browser_thread_impl.h
+++ b/chromium/content/browser/browser_thread_impl.h
@@ -12,6 +12,8 @@
namespace content {
+// Very few users should use this directly. To mock BrowserThreads, tests should
+// use TestBrowserThreadBundle instead.
class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread,
public base::Thread {
public:
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index 0538819fa3d..71cd598236d 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -27,9 +27,7 @@ class BrowserThreadTest : public testing::Test {
base::MessageLoop::QuitWhenIdleClosure());
}
- void StopFileThread() {
- file_thread_->Stop();
- }
+ void StopUIThread() { ui_thread_->Stop(); }
protected:
void SetUp() override {
@@ -40,8 +38,8 @@ class BrowserThreadTest : public testing::Test {
}
void TearDown() override {
- ui_thread_->Stop();
- StopFileThread();
+ StopUIThread();
+ file_thread_->Stop();
}
static void BasicFunction(base::MessageLoop* message_loop) {
@@ -78,22 +76,22 @@ class BrowserThreadTest : public testing::Test {
mutable base::MessageLoop loop_;
};
-class FileThreadDestructionObserver
+class UIThreadDestructionObserver
: public base::MessageLoop::DestructionObserver {
public:
- explicit FileThreadDestructionObserver(bool* did_shutdown,
- const base::Closure& callback)
+ explicit UIThreadDestructionObserver(bool* did_shutdown,
+ const base::Closure& callback)
: callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
callback_(callback),
- file_task_runner_(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)),
+ ui_task_runner_(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
did_shutdown_(did_shutdown) {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)->PostTask(
- FROM_HERE, base::Bind(&Watch, this));
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
+ ->PostTask(FROM_HERE, base::Bind(&Watch, this));
}
private:
- static void Watch(FileThreadDestructionObserver* observer) {
+ static void Watch(UIThreadDestructionObserver* observer) {
base::MessageLoop::current()->AddDestructionObserver(observer);
}
@@ -102,8 +100,8 @@ class FileThreadDestructionObserver
// Ensure that even during MessageLoop teardown the BrowserThread ID is
// correctly associated with this thread and the BrowserThreadTaskRunner
// knows it's on the right thread.
- EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- EXPECT_TRUE(file_task_runner_->BelongsToCurrentThread());
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ EXPECT_TRUE(ui_task_runner_->BelongsToCurrentThread());
base::MessageLoop::current()->RemoveDestructionObserver(this);
*did_shutdown_ = true;
@@ -112,7 +110,7 @@ class FileThreadDestructionObserver
const scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_;
const base::Closure callback_;
- const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
bool* did_shutdown_;
};
@@ -165,10 +163,10 @@ TEST_F(BrowserThreadTest, PostTaskAndReply) {
TEST_F(BrowserThreadTest, RunsTasksOnCurrentThreadDuringShutdown) {
bool did_shutdown = false;
base::RunLoop loop;
- FileThreadDestructionObserver observer(&did_shutdown, loop.QuitClosure());
+ UIThreadDestructionObserver observer(&did_shutdown, loop.QuitClosure());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&BrowserThreadTest::StopFileThread, base::Unretained(this)));
+ base::Bind(&BrowserThreadTest::StopUIThread, base::Unretained(this)));
loop.Run();
EXPECT_TRUE(did_shutdown);
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index ec6723e8ee2..ce791fe82e8 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -127,12 +127,12 @@ class CacheStorage::CacheLoader {
// the cache if necessary.
virtual void NotifyCacheCreated(
const std::string& cache_name,
- std::unique_ptr<CacheStorageCacheHandle> cache_handle) {};
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle) {}
// Notification that the cache for |cache_handle| has been doomed. If the
// loader is holding a handle to the cache, it should drop it now.
virtual void NotifyCacheDoomed(
- std::unique_ptr<CacheStorageCacheHandle> cache_handle) {};
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle) {}
protected:
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
@@ -309,13 +309,13 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
// 1. Create the index file as a string. (WriteIndex)
// 2. Write the file to disk. (WriteIndexWriteToFileInPool)
- CacheStorageIndex index;
+ proto::CacheStorageIndex index;
index.set_origin(origin_.spec());
for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
DCHECK(base::ContainsKey(cache_name_to_cache_dir_, cache_names[i]));
- CacheStorageIndex::Cache* index_cache = index.add_cache();
+ proto::CacheStorageIndex::Cache* index_cache = index.add_cache();
index_cache->set_name(cache_names[i]);
index_cache->set_cache_dir(cache_name_to_cache_dir_[cache_names[i]]);
}
@@ -374,10 +374,10 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
std::unique_ptr<std::set<std::string>> cache_dirs(
new std::set<std::string>);
- CacheStorageIndex index;
+ proto::CacheStorageIndex index;
if (index.ParseFromString(serialized)) {
for (int i = 0, max = index.cache_size(); i < max; ++i) {
- const CacheStorageIndex::Cache& cache = index.cache(i);
+ const proto::CacheStorageIndex::Cache& cache = index.cache(i);
DCHECK(cache.has_cache_dir());
names->push_back(cache.name());
cache_name_to_cache_dir_[cache.name()] = cache.cache_dir();
@@ -427,7 +427,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
static std::string MigrateCachesIfNecessaryInPool(
const std::string& body,
const base::FilePath& index_path) {
- CacheStorageIndex index;
+ proto::CacheStorageIndex index;
if (!index.ParseFromString(body))
return body;
@@ -438,7 +438,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
// Look for caches that have no cache_dir. Give any such caches a directory
// with a random name and move them there. Then, rewrite the index file.
for (int i = 0, max = index.cache_size(); i < max; ++i) {
- const CacheStorageIndex::Cache& cache = index.cache(i);
+ const proto::CacheStorageIndex::Cache& cache = index.cache(i);
if (!cache.has_cache_dir()) {
// Find a new home for the cache.
base::FilePath legacy_cache_path =
@@ -570,7 +570,7 @@ void CacheStorage::DeleteCache(const std::string& cache_name,
cache_name, scheduler_->WrapCallbackToRunNext(callback)));
}
-void CacheStorage::EnumerateCaches(const StringsAndErrorCallback& callback) {
+void CacheStorage::EnumerateCaches(const StringsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!initialized_)
@@ -835,9 +835,8 @@ void CacheStorage::DeleteCacheDidGetSize(
cache_loader_->CleanUpDeletedCache(cache.get());
}
-void CacheStorage::EnumerateCachesImpl(
- const StringsAndErrorCallback& callback) {
- callback.Run(ordered_cache_names_, CACHE_STORAGE_OK);
+void CacheStorage::EnumerateCachesImpl(const StringsCallback& callback) {
+ callback.Run(ordered_cache_names_);
}
void CacheStorage::MatchCacheImpl(
@@ -946,10 +945,11 @@ void CacheStorage::DropCacheHandleRef(CacheStorageCache* cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = cache_handle_counts_.find(cache);
DCHECK(iter != cache_handle_counts_.end());
- DCHECK(iter->second >= 1);
+ DCHECK_GE(iter->second, 1U);
iter->second -= 1;
if (iter->second == 0) {
+ cache_handle_counts_.erase(iter);
auto doomed_caches_iter = doomed_caches_.find(cache);
if (doomed_caches_iter != doomed_caches_.end()) {
// The last reference to a doomed cache is gone, perform clean up.
@@ -962,7 +962,6 @@ void CacheStorage::DropCacheHandleRef(CacheStorageCache* cache) {
DCHECK(cache_map_iter != cache_map_.end());
cache_map_iter->second.reset();
- cache_handle_counts_.erase(iter);
}
}
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index 798206b116d..e0569f19716 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -8,7 +8,9 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <string>
+#include <vector>
#include "base/callback.h"
#include "base/files/file_path.h"
@@ -30,8 +32,8 @@ class BlobStorageContext;
}
namespace content {
-class CacheStorageScheduler;
class CacheStorageCacheHandle;
+class CacheStorageScheduler;
// TODO(jkarlin): Constrain the total bytes used per origin.
@@ -45,8 +47,7 @@ class CONTENT_EXPORT CacheStorage {
typedef base::Callback<void(std::unique_ptr<CacheStorageCacheHandle>,
CacheStorageError)>
CacheAndErrorCallback;
- typedef base::Callback<void(const StringVector&, CacheStorageError)>
- StringsAndErrorCallback;
+ using StringsCallback = base::Callback<void(const StringVector&)>;
using SizeCallback = base::Callback<void(int64_t)>;
static const char kIndexFileName[];
@@ -86,7 +87,7 @@ class CONTENT_EXPORT CacheStorage {
const BoolAndErrorCallback& callback);
// Calls the callback with a vector of cache names (keys) available.
- void EnumerateCaches(const StringsAndErrorCallback& callback);
+ void EnumerateCaches(const StringsCallback& callback);
// Calls match on the cache with the given |cache_name|.
void MatchCache(const std::string& cache_name,
@@ -171,7 +172,7 @@ class CONTENT_EXPORT CacheStorage {
void DeleteCacheDidCleanUp(bool success);
// The EnumerateCache callbacks are below.
- void EnumerateCachesImpl(const StringsAndErrorCallback& callback);
+ void EnumerateCachesImpl(const StringsCallback& callback);
// The MatchCache callbacks are below.
void MatchCacheImpl(const std::string& cache_name,
diff --git a/chromium/content/browser/cache_storage/cache_storage.proto b/chromium/content/browser/cache_storage/cache_storage.proto
index a80b243e186..1021d87320c 100644
--- a/chromium/content/browser/cache_storage/cache_storage.proto
+++ b/chromium/content/browser/cache_storage/cache_storage.proto
@@ -6,7 +6,7 @@ syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package content;
+package content.proto;
message CacheStorageIndex {
message Cache {
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index 5c48906c9be..77286600d22 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -5,6 +5,9 @@
#include "content/browser/cache_storage/cache_storage_cache.h"
#include <stddef.h>
+#include <algorithm>
+#include <limits>
+#include <memory>
#include <string>
#include <utility>
@@ -62,50 +65,51 @@ class CacheStorageCacheDataHandle
DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheDataHandle);
};
-typedef base::Callback<void(std::unique_ptr<CacheMetadata>)> MetadataCallback;
+typedef base::Callback<void(std::unique_ptr<proto::CacheMetadata>)>
+ MetadataCallback;
// The maximum size of each cache. Ultimately, cache size
// is controlled per-origin by the QuotaManager.
const int kMaxCacheBytes = std::numeric_limits<int>::max();
blink::WebServiceWorkerResponseType ProtoResponseTypeToWebResponseType(
- CacheResponse::ResponseType response_type) {
+ proto::CacheResponse::ResponseType response_type) {
switch (response_type) {
- case CacheResponse::BASIC_TYPE:
+ case proto::CacheResponse::BASIC_TYPE:
return blink::WebServiceWorkerResponseTypeBasic;
- case CacheResponse::CORS_TYPE:
+ case proto::CacheResponse::CORS_TYPE:
return blink::WebServiceWorkerResponseTypeCORS;
- case CacheResponse::DEFAULT_TYPE:
+ case proto::CacheResponse::DEFAULT_TYPE:
return blink::WebServiceWorkerResponseTypeDefault;
- case CacheResponse::ERROR_TYPE:
+ case proto::CacheResponse::ERROR_TYPE:
return blink::WebServiceWorkerResponseTypeError;
- case CacheResponse::OPAQUE_TYPE:
+ case proto::CacheResponse::OPAQUE_TYPE:
return blink::WebServiceWorkerResponseTypeOpaque;
- case CacheResponse::OPAQUE_REDIRECT_TYPE:
+ case proto::CacheResponse::OPAQUE_REDIRECT_TYPE:
return blink::WebServiceWorkerResponseTypeOpaqueRedirect;
}
NOTREACHED();
return blink::WebServiceWorkerResponseTypeOpaque;
}
-CacheResponse::ResponseType WebResponseTypeToProtoResponseType(
+proto::CacheResponse::ResponseType WebResponseTypeToProtoResponseType(
blink::WebServiceWorkerResponseType response_type) {
switch (response_type) {
case blink::WebServiceWorkerResponseTypeBasic:
- return CacheResponse::BASIC_TYPE;
+ return proto::CacheResponse::BASIC_TYPE;
case blink::WebServiceWorkerResponseTypeCORS:
- return CacheResponse::CORS_TYPE;
+ return proto::CacheResponse::CORS_TYPE;
case blink::WebServiceWorkerResponseTypeDefault:
- return CacheResponse::DEFAULT_TYPE;
+ return proto::CacheResponse::DEFAULT_TYPE;
case blink::WebServiceWorkerResponseTypeError:
- return CacheResponse::ERROR_TYPE;
+ return proto::CacheResponse::ERROR_TYPE;
case blink::WebServiceWorkerResponseTypeOpaque:
- return CacheResponse::OPAQUE_TYPE;
+ return proto::CacheResponse::OPAQUE_TYPE;
case blink::WebServiceWorkerResponseTypeOpaqueRedirect:
- return CacheResponse::OPAQUE_REDIRECT_TYPE;
+ return proto::CacheResponse::OPAQUE_REDIRECT_TYPE;
}
NOTREACHED();
- return CacheResponse::OPAQUE_TYPE;
+ return proto::CacheResponse::OPAQUE_TYPE;
}
// Copy headers out of a cache entry and into a protobuf. The callback is
@@ -176,14 +180,14 @@ void ReadMetadataDidReadMetadata(disk_cache::Entry* entry,
scoped_refptr<net::IOBufferWithSize> buffer,
int rv) {
if (rv != buffer->size()) {
- callback.Run(std::unique_ptr<CacheMetadata>());
+ callback.Run(std::unique_ptr<proto::CacheMetadata>());
return;
}
- std::unique_ptr<CacheMetadata> metadata(new CacheMetadata());
+ std::unique_ptr<proto::CacheMetadata> metadata(new proto::CacheMetadata());
if (!metadata->ParseFromArray(buffer->data(), buffer->size())) {
- callback.Run(std::unique_ptr<CacheMetadata>());
+ callback.Run(std::unique_ptr<proto::CacheMetadata>());
return;
}
@@ -660,7 +664,7 @@ void CacheStorageCache::QueryCacheFilterEntry(
void CacheStorageCache::QueryCacheDidReadMetadata(
std::unique_ptr<QueryCacheContext> query_cache_context,
disk_cache::ScopedEntryPtr entry,
- std::unique_ptr<CacheMetadata> metadata) {
+ std::unique_ptr<proto::CacheMetadata> metadata) {
if (!metadata) {
entry->Doom();
QueryCacheOpenNextEntry(std::move(query_cache_context));
@@ -895,7 +899,7 @@ void CacheStorageCache::WriteSideDataDidReadMetaData(
scoped_refptr<net::IOBuffer> buffer,
int buf_len,
disk_cache::ScopedEntryPtr entry,
- std::unique_ptr<CacheMetadata> headers) {
+ std::unique_ptr<proto::CacheMetadata> headers) {
if (!headers ||
headers->response().response_time() !=
expected_response_time.ToInternalValue()) {
@@ -1045,21 +1049,21 @@ void CacheStorageCache::PutDidCreateEntry(
return;
}
- CacheMetadata metadata;
+ proto::CacheMetadata metadata;
metadata.set_entry_time(base::Time::Now().ToInternalValue());
- CacheRequest* request_metadata = metadata.mutable_request();
+ proto::CacheRequest* request_metadata = metadata.mutable_request();
request_metadata->set_method(put_context->request->method);
for (ServiceWorkerHeaderMap::const_iterator it =
put_context->request->headers.begin();
it != put_context->request->headers.end(); ++it) {
DCHECK_EQ(std::string::npos, it->first.find('\0'));
DCHECK_EQ(std::string::npos, it->second.find('\0'));
- CacheHeaderMap* header_map = request_metadata->add_headers();
+ proto::CacheHeaderMap* header_map = request_metadata->add_headers();
header_map->set_name(it->first);
header_map->set_value(it->second);
}
- CacheResponse* response_metadata = metadata.mutable_response();
+ 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(
@@ -1072,7 +1076,7 @@ void CacheStorageCache::PutDidCreateEntry(
it != put_context->response->headers.end(); ++it) {
DCHECK_EQ(std::string::npos, it->first.find('\0'));
DCHECK_EQ(std::string::npos, it->second.find('\0'));
- CacheHeaderMap* header_map = response_metadata->add_headers();
+ proto::CacheHeaderMap* header_map = response_metadata->add_headers();
header_map->set_name(it->first);
header_map->set_value(it->second);
}
@@ -1385,7 +1389,7 @@ void CacheStorageCache::InitGotCacheSize(const base::Closure& callback,
}
void CacheStorageCache::PopulateRequestFromMetadata(
- const CacheMetadata& metadata,
+ const proto::CacheMetadata& metadata,
const GURL& request_url,
ServiceWorkerFetchRequest* request) {
*request =
@@ -1393,7 +1397,7 @@ void CacheStorageCache::PopulateRequestFromMetadata(
ServiceWorkerHeaderMap(), Referrer(), false);
for (int i = 0; i < metadata.request().headers_size(); ++i) {
- const CacheHeaderMap header = metadata.request().headers(i);
+ const proto::CacheHeaderMap header = metadata.request().headers(i);
DCHECK_EQ(std::string::npos, header.name().find('\0'));
DCHECK_EQ(std::string::npos, header.value().find('\0'));
request->headers.insert(std::make_pair(header.name(), header.value()));
@@ -1401,7 +1405,7 @@ void CacheStorageCache::PopulateRequestFromMetadata(
}
void CacheStorageCache::PopulateResponseMetadata(
- const CacheMetadata& metadata,
+ const proto::CacheMetadata& metadata,
ServiceWorkerResponse* response) {
*response = ServiceWorkerResponse(
GURL(metadata.response().url()), metadata.response().status_code(),
@@ -1416,7 +1420,7 @@ void CacheStorageCache::PopulateResponseMetadata(
metadata.response().cors_exposed_header_names().end()));
for (int i = 0; i < metadata.response().headers_size(); ++i) {
- const CacheHeaderMap header = metadata.response().headers(i);
+ const proto::CacheHeaderMap header = metadata.response().headers(i);
DCHECK_EQ(std::string::npos, header.name().find('\0'));
DCHECK_EQ(std::string::npos, header.value().find('\0'));
response->headers.insert(std::make_pair(header.name(), header.value()));
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index 33b46bdb4f2..e9566424eb8 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <memory>
+#include <string>
#include <vector>
#include "base/callback.h"
@@ -22,7 +24,6 @@
namespace net {
class URLRequestContextGetter;
-class IOBufferWithSize;
}
namespace storage {
@@ -35,10 +36,13 @@ namespace content {
class CacheStorage;
class CacheStorageBlobToDiskCache;
class CacheStorageCacheHandle;
-class CacheMetadata;
class CacheStorageScheduler;
class TestCacheStorageCache;
+namespace proto {
+class CacheMetadata;
+}
+
// Represents a ServiceWorker Cache as seen in
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ The
// asynchronous methods are executed serially. Callbacks to the public functions
@@ -222,7 +226,7 @@ class CONTENT_EXPORT CacheStorageCache {
void QueryCacheDidReadMetadata(
std::unique_ptr<QueryCacheContext> query_cache_context,
disk_cache::ScopedEntryPtr entry,
- std::unique_ptr<CacheMetadata> metadata);
+ std::unique_ptr<proto::CacheMetadata> metadata);
static bool QueryCacheResultCompare(const QueryCacheResult& lhs,
const QueryCacheResult& rhs);
@@ -273,12 +277,13 @@ class CONTENT_EXPORT CacheStorageCache {
int buf_len,
std::unique_ptr<disk_cache::Entry*> entry_ptr,
int rv);
- void WriteSideDataDidReadMetaData(const ErrorCallback& callback,
- base::Time expected_response_time,
- scoped_refptr<net::IOBuffer> buffer,
- int buf_len,
- disk_cache::ScopedEntryPtr entry,
- std::unique_ptr<CacheMetadata> headers);
+ void WriteSideDataDidReadMetaData(
+ const ErrorCallback& callback,
+ base::Time expected_response_time,
+ scoped_refptr<net::IOBuffer> buffer,
+ int buf_len,
+ disk_cache::ScopedEntryPtr entry,
+ std::unique_ptr<proto::CacheMetadata> headers);
void WriteSideDataDidWrite(const ErrorCallback& callback,
disk_cache::ScopedEntryPtr entry,
int expected_bytes,
@@ -354,10 +359,10 @@ class CONTENT_EXPORT CacheStorageCache {
CacheStorageError cache_create_error,
int cache_size);
- void PopulateRequestFromMetadata(const CacheMetadata& metadata,
+ void PopulateRequestFromMetadata(const proto::CacheMetadata& metadata,
const GURL& request_url,
ServiceWorkerFetchRequest* request);
- void PopulateResponseMetadata(const CacheMetadata& metadata,
+ void PopulateResponseMetadata(const proto::CacheMetadata& metadata,
ServiceWorkerResponse* response);
std::unique_ptr<storage::BlobDataHandle> PopulateResponseBody(
disk_cache::ScopedEntryPtr entry,
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 1834e8f3d12..ead0d38f9ed 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <memory>
+#include <set>
#include <utility>
#include "base/files/file_path.h"
@@ -62,7 +63,7 @@ std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
// A disk_cache::Backend wrapper that can delay operations.
class DelayableBackend : public disk_cache::Backend {
public:
- DelayableBackend(std::unique_ptr<disk_cache::Backend> backend)
+ explicit DelayableBackend(std::unique_ptr<disk_cache::Backend> backend)
: backend_(std::move(backend)), delay_doom_(false) {}
// disk_cache::Backend overrides
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 e2988289d5a..bd0a3207393 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
@@ -24,7 +24,6 @@ class URLRequestContextGetter;
namespace storage {
class QuotaManagerProxy;
-class SpecialStoragePolicy;
}
namespace content {
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index 04138969b4a..ba584c7a92e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -61,7 +61,7 @@ blink::WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
}
bool OriginCanAccessCacheStorage(const url::Origin& origin) {
- return !origin.unique() && IsOriginSecure(GURL(origin.Serialize()));
+ return !origin.unique() && IsOriginSecure(origin.GetURL());
}
void StopPreservingCache(
@@ -132,7 +132,7 @@ void CacheStorageDispatcherHost::OnCacheStorageHas(
return;
}
context_->cache_manager()->HasCache(
- GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
+ origin.GetURL(), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageHasCallback, this,
thread_id, request_id));
}
@@ -149,7 +149,7 @@ void CacheStorageDispatcherHost::OnCacheStorageOpen(
return;
}
context_->cache_manager()->OpenCache(
- GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
+ origin.GetURL(), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageOpenCallback, this,
thread_id, request_id));
}
@@ -166,7 +166,7 @@ void CacheStorageDispatcherHost::OnCacheStorageDelete(
return;
}
context_->cache_manager()->DeleteCache(
- GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
+ origin.GetURL(), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageDeleteCallback,
this, thread_id, request_id));
}
@@ -181,7 +181,7 @@ void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id,
return;
}
context_->cache_manager()->EnumerateCaches(
- GURL(origin.Serialize()),
+ origin.GetURL(),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageKeysCallback, this,
thread_id, request_id));
}
@@ -205,14 +205,13 @@ void CacheStorageDispatcherHost::OnCacheStorageMatch(
if (match_params.cache_name.is_null()) {
context_->cache_manager()->MatchAllCaches(
- GURL(origin.Serialize()), std::move(scoped_request), match_params,
+ origin.GetURL(), std::move(scoped_request), match_params,
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback,
this, thread_id, request_id));
return;
}
context_->cache_manager()->MatchCache(
- GURL(origin.Serialize()),
- base::UTF16ToUTF8(match_params.cache_name.string()),
+ origin.GetURL(), base::UTF16ToUTF8(match_params.cache_name.string()),
std::move(scoped_request), match_params,
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback, this,
thread_id, request_id));
@@ -390,18 +389,10 @@ void CacheStorageDispatcherHost::OnCacheStorageDeleteCallback(
void CacheStorageDispatcherHost::OnCacheStorageKeysCallback(
int thread_id,
int request_id,
- const std::vector<std::string>& strings,
- CacheStorageError error) {
- if (error != CACHE_STORAGE_OK) {
- Send(new CacheStorageMsg_CacheStorageKeysError(
- thread_id, request_id, ToWebServiceWorkerCacheError(error)));
- return;
- }
-
+ const std::vector<std::string>& strings) {
std::vector<base::string16> string16s;
- for (size_t i = 0, max = strings.size(); i < max; ++i) {
+ for (size_t i = 0, max = strings.size(); i < max; ++i)
string16s.push_back(base::UTF8ToUTF16(strings[i]));
- }
Send(new CacheStorageMsg_CacheStorageKeysSuccess(thread_id, request_id,
string16s));
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
index d937bac0348..e82018a9171 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -8,6 +8,10 @@
#include <stdint.h>
#include <list>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
#include "base/macros.h"
#include "content/browser/cache_storage/cache_storage.h"
@@ -107,8 +111,7 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
CacheStorageError error);
void OnCacheStorageKeysCallback(int thread_id,
int request_id,
- const std::vector<std::string>& strings,
- CacheStorageError error);
+ const std::vector<std::string>& strings);
void OnCacheStorageMatchCallback(
int thread_id,
int request_id,
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index 9a026aa0b89..6c136ae1ef2 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <map>
+#include <set>
#include <string>
#include <utility>
@@ -63,7 +64,7 @@ void ListOriginsAndLastModifiedOnTaskRunner(
std::string protobuf;
base::ReadFileToString(path.AppendASCII(CacheStorage::kIndexFileName),
&protobuf);
- CacheStorageIndex index;
+ proto::CacheStorageIndex index;
if (index.ParseFromString(protobuf)) {
if (index.has_origin()) {
base::File::Info file_info;
@@ -185,7 +186,7 @@ void CacheStorageManager::DeleteCache(
void CacheStorageManager::EnumerateCaches(
const GURL& origin,
- const CacheStorage::StringsAndErrorCallback& callback) {
+ const CacheStorage::StringsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
@@ -376,7 +377,6 @@ void CacheStorageManager::DeleteOriginDidClose(
return;
}
- MigrateOrigin(origin);
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
base::Bind(&DeleteDir, ConstructOriginPath(root_path_, origin)),
@@ -403,7 +403,6 @@ CacheStorage* CacheStorageManager::FindOrCreateCacheStorage(
DCHECK(request_context_getter_);
CacheStorageMap::const_iterator it = cache_storage_map_.find(origin);
if (it == cache_storage_map_.end()) {
- MigrateOrigin(origin);
CacheStorage* cache_storage = new CacheStorage(
ConstructOriginPath(root_path_, origin), IsMemoryBacked(),
cache_task_runner_.get(), request_context_getter_, quota_manager_proxy_,
@@ -416,16 +415,6 @@ CacheStorage* CacheStorageManager::FindOrCreateCacheStorage(
}
// static
-base::FilePath CacheStorageManager::ConstructLegacyOriginPath(
- const base::FilePath& root_path,
- const GURL& origin) {
- const std::string origin_hash = base::SHA1HashString(origin.spec());
- const std::string origin_hash_hex = base::ToLowerASCII(
- base::HexEncode(origin_hash.c_str(), origin_hash.length()));
- return root_path.AppendASCII(origin_hash_hex);
-}
-
-// static
base::FilePath CacheStorageManager::ConstructOriginPath(
const base::FilePath& root_path,
const GURL& origin) {
@@ -436,26 +425,4 @@ base::FilePath CacheStorageManager::ConstructOriginPath(
return root_path.AppendASCII(origin_hash_hex);
}
-// Migrate from old origin-based path to storage identifier-based path.
-// TODO(jsbell); Remove after a few releases.
-void CacheStorageManager::MigrateOrigin(const GURL& origin) {
- if (IsMemoryBacked())
- return;
- base::FilePath old_path = ConstructLegacyOriginPath(root_path_, origin);
- base::FilePath new_path = ConstructOriginPath(root_path_, origin);
- cache_task_runner_->PostTask(
- FROM_HERE, base::Bind(&MigrateOriginOnTaskRunner, old_path, new_path));
-}
-
-// static
-void CacheStorageManager::MigrateOriginOnTaskRunner(
- const base::FilePath& old_path,
- const base::FilePath& new_path) {
- if (base::PathExists(old_path)) {
- if (!base::PathExists(new_path))
- base::Move(old_path, new_path);
- base::DeleteFile(old_path, /*recursive*/ true);
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index 107b685ba27..f9f95b0dbf8 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -6,7 +6,9 @@
#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_
#include <map>
+#include <memory>
#include <string>
+#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
@@ -64,7 +66,7 @@ class CONTENT_EXPORT CacheStorageManager {
const std::string& cache_name,
const CacheStorage::BoolAndErrorCallback& callback);
void EnumerateCaches(const GURL& origin,
- const CacheStorage::StringsAndErrorCallback& callback);
+ const CacheStorage::StringsCallback& callback);
void MatchCache(const GURL& origin,
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
@@ -90,7 +92,6 @@ class CONTENT_EXPORT CacheStorageManager {
private:
friend class CacheStorageContextImpl;
friend class CacheStorageManagerTest;
- friend class CacheStorageMigrationTest;
friend class CacheStorageQuotaClient;
typedef std::map<GURL, std::unique_ptr<CacheStorage>> CacheStorageMap;
@@ -140,17 +141,6 @@ class CONTENT_EXPORT CacheStorageManager {
bool IsMemoryBacked() const { return root_path_.empty(); }
- // Map a origin to the path. Exposed for testing.
- static base::FilePath ConstructLegacyOriginPath(
- const base::FilePath& root_path,
- const GURL& origin);
-
- // Migrate from old origin-based path to storage identifier-based path.
- // TODO(jsbell); Remove method and all calls after a few releases.
- void MigrateOrigin(const GURL& origin);
- static void MigrateOriginOnTaskRunner(const base::FilePath& old_path,
- const base::FilePath& new_path);
-
base::FilePath root_path_;
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
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 18cc36cef15..90601a61139 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <set>
#include <utility>
#include "base/files/file_path.h"
@@ -134,11 +135,9 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
- void StringsAndErrorCallback(base::RunLoop* run_loop,
- const std::vector<std::string>& strings,
- CacheStorageError error) {
+ void StringsCallback(base::RunLoop* run_loop,
+ const std::vector<std::string>& strings) {
callback_strings_ = strings;
- callback_error_ = error;
run_loop->Quit();
}
@@ -196,14 +195,13 @@ class CacheStorageManagerTest : public testing::Test {
return callback_bool_;
}
- bool Keys(const GURL& origin) {
+ size_t Keys(const GURL& origin) {
base::RunLoop loop;
cache_manager_->EnumerateCaches(
- origin, base::Bind(&CacheStorageManagerTest::StringsAndErrorCallback,
+ origin, base::Bind(&CacheStorageManagerTest::StringsCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
-
- return callback_error_ == CACHE_STORAGE_OK;
+ return callback_strings_.size();
}
bool StorageMatch(const GURL& origin,
@@ -497,22 +495,19 @@ TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) {
}
TEST_P(CacheStorageManagerTestP, EmptyKeys) {
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_TRUE(callback_strings_.empty());
+ EXPECT_EQ(0u, Keys(origin1_));
}
TEST_P(CacheStorageManagerTestP, SomeKeys) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(2u, callback_strings_.size());
+ EXPECT_EQ(2u, Keys(origin1_));
std::vector<std::string> expected_keys;
expected_keys.push_back("foo");
expected_keys.push_back("bar");
EXPECT_EQ(expected_keys, callback_strings_);
- EXPECT_TRUE(Keys(origin2_));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(origin2_));
EXPECT_STREQ("baz", callback_strings_[0].c_str());
}
@@ -521,8 +516,7 @@ TEST_P(CacheStorageManagerTestP, DeletedKeysGone) {
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
EXPECT_TRUE(Delete(origin1_, "bar"));
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("foo", callback_strings_[0].c_str());
}
@@ -668,8 +662,7 @@ TEST_P(CacheStorageManagerTestP, Chinese) {
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "你好"));
EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value());
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("你好", callback_strings_[0].c_str());
}
@@ -679,13 +672,11 @@ TEST_F(CacheStorageManagerTest, EmptyKey) {
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, ""));
EXPECT_EQ(cache_handle->value(), callback_cache_handle_->value());
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("", callback_strings_[0].c_str());
EXPECT_TRUE(Has(origin1_, ""));
EXPECT_TRUE(Delete(origin1_, ""));
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(0u, callback_strings_.size());
+ EXPECT_EQ(0u, Keys(origin1_));
}
TEST_F(CacheStorageManagerTest, DataPersists) {
@@ -696,8 +687,7 @@ TEST_F(CacheStorageManagerTest, DataPersists) {
EXPECT_TRUE(Delete(origin1_, "bar"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(2u, callback_strings_.size());
+ EXPECT_EQ(2u, Keys(origin1_));
std::vector<std::string> expected_keys;
expected_keys.push_back("foo");
expected_keys.push_back("baz");
@@ -709,8 +699,7 @@ TEST_F(CacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
EXPECT_TRUE(Open(origin2_, "baz"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(0u, callback_strings_.size());
+ EXPECT_EQ(0u, Keys(origin1_));
}
TEST_F(CacheStorageManagerTest, BadCacheName) {
@@ -718,8 +707,7 @@ TEST_F(CacheStorageManagerTest, BadCacheName) {
// escape the directory.
const std::string bad_name = "../../../../../../../../../../../../../../foo";
EXPECT_TRUE(Open(origin1_, bad_name));
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ(bad_name.c_str(), callback_strings_[0].c_str());
}
@@ -728,8 +716,7 @@ TEST_F(CacheStorageManagerTest, BadOriginName) {
// escape the directory.
GURL bad_origin("http://../../../../../../../../../../../../../../foo");
EXPECT_TRUE(Open(bad_origin, "foo"));
- EXPECT_TRUE(Keys(bad_origin));
- EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_EQ(1u, Keys(bad_origin));
EXPECT_STREQ("foo", callback_strings_[0].c_str());
}
@@ -766,8 +753,7 @@ TEST_P(CacheStorageManagerTestP, CacheWorksAfterDelete) {
EXPECT_TRUE(CacheMatch(original_handle->value(), kBarURL));
// The cache shouldn't be visible to subsequent storage operations.
- EXPECT_TRUE(Keys(origin1_));
- EXPECT_TRUE(callback_strings_.empty());
+ EXPECT_EQ(0u, Keys(origin1_));
// Open a new cache with the same name, it should create a new cache, but not
// interfere with the original cache.
@@ -939,7 +925,7 @@ TEST_P(CacheStorageManagerTestP, DeleteStorageAccessed) {
TEST_P(CacheStorageManagerTestP, KeysStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
- EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(0u, Keys(origin1_));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
@@ -1072,198 +1058,6 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, request, match_params));
}
-class CacheStorageMigrationTest : public CacheStorageManagerTest {
- protected:
- CacheStorageMigrationTest() : cache1_("foo"), cache2_("bar") {}
-
- void SetUp() override {
- CacheStorageManagerTest::SetUp();
-
- // Populate a cache, then move it to the "legacy" location
- // so that tests can verify the results of migration.
- legacy_path_ = CacheStorageManager::ConstructLegacyOriginPath(
- cache_manager_->root_path(), origin1_);
- new_path_ = CacheStorageManager::ConstructOriginPath(
- cache_manager_->root_path(), origin1_);
-
- ASSERT_FALSE(base::DirectoryExists(legacy_path_));
- ASSERT_FALSE(base::DirectoryExists(new_path_));
- ASSERT_TRUE(Open(origin1_, cache1_));
- ASSERT_TRUE(Open(origin1_, cache2_));
- callback_cache_handle_.reset();
-
- // Let the caches shut down.
- base::RunLoop().RunUntilIdle();
-
- ASSERT_FALSE(base::DirectoryExists(legacy_path_));
- ASSERT_TRUE(base::DirectoryExists(new_path_));
-
- quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
-
- ASSERT_TRUE(base::Move(new_path_, legacy_path_));
- ASSERT_TRUE(base::DirectoryExists(legacy_path_));
- ASSERT_FALSE(base::DirectoryExists(new_path_));
- }
-
- base::FilePath legacy_path_;
- base::FilePath new_path_;
-
- const std::string cache1_;
- const std::string cache2_;
-
- DISALLOW_COPY_AND_ASSIGN(CacheStorageMigrationTest);
-};
-
-TEST_F(CacheStorageMigrationTest, OpenCache) {
- EXPECT_TRUE(Open(origin1_, cache1_));
- EXPECT_FALSE(base::DirectoryExists(legacy_path_));
- EXPECT_TRUE(base::DirectoryExists(new_path_));
-
- EXPECT_TRUE(Keys(origin1_));
- std::vector<std::string> expected_keys;
- expected_keys.push_back(cache1_);
- expected_keys.push_back(cache2_);
- EXPECT_EQ(expected_keys, callback_strings_);
-}
-
-TEST_F(CacheStorageMigrationTest, DeleteCache) {
- EXPECT_TRUE(Delete(origin1_, cache1_));
- EXPECT_FALSE(base::DirectoryExists(legacy_path_));
- EXPECT_TRUE(base::DirectoryExists(new_path_));
-
- EXPECT_TRUE(Keys(origin1_));
- std::vector<std::string> expected_keys;
- expected_keys.push_back(cache2_);
- EXPECT_EQ(expected_keys, callback_strings_);
-}
-
-TEST_F(CacheStorageMigrationTest, GetOriginUsage) {
- EXPECT_EQ(0, GetOriginUsage(origin1_));
- EXPECT_FALSE(base::DirectoryExists(legacy_path_));
- EXPECT_TRUE(base::DirectoryExists(new_path_));
-}
-
-TEST_F(CacheStorageMigrationTest, MoveFailure) {
- // Revert the migration.
- ASSERT_TRUE(base::Move(legacy_path_, new_path_));
- ASSERT_FALSE(base::DirectoryExists(legacy_path_));
- ASSERT_TRUE(base::DirectoryExists(new_path_));
-
- // Make a dummy legacy directory.
- ASSERT_TRUE(base::CreateDirectory(legacy_path_));
-
- // Ensure that migration doesn't stomp existing new directory,
- // but does clean up old directory.
- EXPECT_TRUE(Open(origin1_, cache1_));
- EXPECT_FALSE(base::DirectoryExists(legacy_path_));
- EXPECT_TRUE(base::DirectoryExists(new_path_));
-
- EXPECT_TRUE(Keys(origin1_));
- std::vector<std::string> expected_keys;
- expected_keys.push_back(cache1_);
- expected_keys.push_back(cache2_);
- EXPECT_EQ(expected_keys, callback_strings_);
-}
-
-// Tests that legacy caches created via a hash of the cache name instead of a
-// random name are migrated and continue to function in a new world of random
-// cache names.
-class MigratedLegacyCacheDirectoryNameTest : public CacheStorageManagerTest {
- protected:
- MigratedLegacyCacheDirectoryNameTest()
- : legacy_cache_name_("foo"), stored_url_("http://example.com/foo") {}
-
- void SetUp() override {
- CacheStorageManagerTest::SetUp();
-
- // Create a cache that is stored on disk with the legacy naming scheme (hash
- // of the name) and without a directory name in the index.
- base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
- cache_manager_->root_path(), origin1_);
-
- // Populate a legacy cache.
- ASSERT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_TRUE(CachePut(callback_cache_handle_->value(), stored_url_));
- base::FilePath new_path = callback_cache_handle_->value()->path();
-
- // Close the cache's backend so that the files can be moved.
- callback_cache_handle_->value()->Close(base::Bind(&base::DoNothing));
- base::RunLoop().RunUntilIdle();
-
- // Legacy index files didn't have the cache directory, so remove it from the
- // index.
- base::FilePath index_path = origin_path.AppendASCII("index.txt");
- std::string index_contents;
- base::ReadFileToString(index_path, &index_contents);
- CacheStorageIndex index;
- ASSERT_TRUE(index.ParseFromString(index_contents));
- ASSERT_EQ(1, index.cache_size());
- index.mutable_cache(0)->clear_cache_dir();
- ASSERT_TRUE(index.SerializeToString(&index_contents));
- index.ParseFromString(index_contents);
- ASSERT_EQ(index_contents.size(),
- (uint32_t)base::WriteFile(index_path, index_contents.c_str(),
- index_contents.size()));
-
- // Move the cache to the legacy location.
- legacy_path_ = origin_path.AppendASCII(HexedHash(legacy_cache_name_));
- ASSERT_FALSE(base::DirectoryExists(legacy_path_));
- ASSERT_TRUE(base::Move(new_path, legacy_path_));
-
- // Create a new manager to reread the index file and force migration.
- quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
- }
-
- static std::string HexedHash(const std::string& value) {
- std::string value_hash = base::SHA1HashString(value);
- std::string valued_hexed_hash = base::ToLowerASCII(
- base::HexEncode(value_hash.c_str(), value_hash.length()));
- return valued_hexed_hash;
- }
-
- base::FilePath legacy_path_;
- const std::string legacy_cache_name_;
- const GURL stored_url_;
-
- DISALLOW_COPY_AND_ASSIGN(MigratedLegacyCacheDirectoryNameTest);
-};
-
-TEST_F(MigratedLegacyCacheDirectoryNameTest, LegacyCacheMigrated) {
- EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
-
- // Verify that the cache migrated away from the legacy_path_ directory.
- ASSERT_FALSE(base::DirectoryExists(legacy_path_));
-
- // Verify that the existing entry still works.
- EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), stored_url_));
-
- // Verify that adding new entries works.
- EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
- GURL("http://example.com/foo2")));
- EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(),
- GURL("http://example.com/foo2")));
-}
-
-TEST_F(MigratedLegacyCacheDirectoryNameTest,
- RandomDirectoryCacheSideBySideWithLegacy) {
- EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_handle_->value(), stored_url_));
- EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), stored_url_));
-}
-
-TEST_F(MigratedLegacyCacheDirectoryNameTest, DeleteLegacyCacheAndRecreateNew) {
- EXPECT_TRUE(Delete(origin1_, legacy_cache_name_));
- EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_FALSE(CacheMatch(callback_cache_handle_->value(), stored_url_));
- EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
- GURL("http://example.com/foo2")));
- EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(),
- GURL("http://example.com/foo2")));
-}
-
class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
protected:
CacheStorageQuotaClientTest() {}
@@ -1340,6 +1134,7 @@ class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
int64_t callback_quota_usage_ = 0;
std::set<GURL> callback_origins_;
+ private:
DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClientTest);
};
diff --git a/chromium/content/browser/cache_storage/cache_storage_operation.h b/chromium/content/browser/cache_storage/cache_storage_operation.h
index 28af48d9ad5..124dc5a319d 100644
--- a/chromium/content/browser/cache_storage/cache_storage_operation.h
+++ b/chromium/content/browser/cache_storage/cache_storage_operation.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "content/browser/cache_storage/cache_storage_scheduler_client.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/cache_storage/cache_storage_quota_client.h b/chromium/content/browser/cache_storage/cache_storage_quota_client.h
index 941bf8ba98d..367f2704af8 100644
--- a/chromium/content/browser/cache_storage/cache_storage_quota_client.h
+++ b/chromium/content/browser/cache_storage/cache_storage_quota_client.h
@@ -11,10 +11,6 @@
#include "storage/browser/quota/quota_client.h"
#include "storage/common/quota/quota_types.h"
-namespace storage {
-class QuotaManagerProxy;
-}
-
namespace content {
class CacheStorageManager;
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index 0d640fae6ab..e2c042644f1 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -12,6 +12,7 @@
#include "base/files/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/launch.h"
#include "base/process/process.h"
@@ -66,10 +67,10 @@ namespace {
typedef base::Callback<void(ZygoteHandle,
#if defined(OS_ANDROID)
base::ScopedFD,
- base::ScopedFD,
#endif
base::Process,
- int)> NotifyCallback;
+ int)>
+ NotifyCallback;
void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
@@ -90,7 +91,6 @@ void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
void OnChildProcessStartedAndroid(const NotifyCallback& callback,
BrowserThread::ID client_thread_id,
const base::TimeTicks begin_launch_time,
- base::ScopedFD ipcfd,
base::ScopedFD mojo_fd,
base::ProcessHandle handle) {
int launch_result = (handle == base::kNullProcessHandle)
@@ -102,9 +102,9 @@ void OnChildProcessStartedAndroid(const NotifyCallback& callback,
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
- base::Closure callback_on_client_thread(base::Bind(
- callback, nullptr, base::Passed(&ipcfd), base::Passed(&mojo_fd),
- base::Passed(base::Process(handle)), launch_result));
+ base::Closure callback_on_client_thread(
+ base::Bind(callback, nullptr, base::Passed(&mojo_fd),
+ base::Passed(base::Process(handle)), launch_result));
if (BrowserThread::CurrentlyOn(client_thread_id)) {
callback_on_client_thread.Run();
} else {
@@ -118,9 +118,6 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
BrowserThread::ID client_thread_id,
int child_process_id,
SandboxedProcessLauncherDelegate* delegate,
-#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
-#endif
mojo::edk::ScopedPlatformHandle client_handle,
base::CommandLine* cmd_line) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
@@ -133,10 +130,8 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
bool launch_elevated = delegate->ShouldLaunchElevated();
#elif defined(OS_MACOSX)
base::EnvironmentMap env = delegate->GetEnvironment();
- base::ScopedFD ipcfd = delegate->TakeIpcFd();
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
base::EnvironmentMap env = delegate->GetEnvironment();
- base::ScopedFD ipcfd = delegate->TakeIpcFd();
#endif
std::unique_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
base::TimeTicks begin_launch_time = base::TimeTicks::Now();
@@ -152,6 +147,7 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
} else {
base::HandlesToInheritVector handles;
handles.push_back(client_handle.get().handle);
+ base::FieldTrialList::AppendFieldTrialHandleIfNeeded(&handles);
cmd_line->AppendSwitchASCII(
mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
base::UintToString(base::win::HandleToUint32(handles[0])));
@@ -168,12 +164,8 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
DCHECK(mojo_fd.is_valid());
#if defined(OS_ANDROID)
- if (ipcfd.get() != -1)
- files_to_register->Share(kPrimaryIPCChannel, ipcfd.get());
files_to_register->Share(kMojoIPCChannel, mojo_fd.get());
#else
- if (ipcfd.get() != -1)
- files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd));
files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd));
#endif
#endif
@@ -251,8 +243,7 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
StartChildProcess(
cmd_line->argv(), child_process_id, std::move(files_to_register), regions,
base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
- begin_launch_time, base::Passed(&ipcfd),
- base::Passed(&mojo_fd)));
+ begin_launch_time, base::Passed(&mojo_fd)));
#elif defined(OS_POSIX)
// We need to close the client end of the IPC channel to reliably detect
@@ -383,7 +374,11 @@ void SetProcessBackgroundedOnLauncherThread(base::Process process,
bool background) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
if (process.CanBackgroundProcesses()) {
+#if defined(OS_MACOSX)
+ process.SetProcessBackgrounded(MachBroker::GetInstance(), background);
+#else
process.SetProcessBackgrounded(background);
+#endif // defined(OS_MACOSX)
}
#if defined(OS_ANDROID)
SetChildProcessInForeground(process.Handle(), !background);
@@ -431,10 +426,9 @@ ChildProcessLauncher::~ChildProcessLauncher() {
}
}
-void ChildProcessLauncher::Launch(
- SandboxedProcessLauncherDelegate* delegate,
- base::CommandLine* cmd_line,
- int child_process_id) {
+void ChildProcessLauncher::Launch(SandboxedProcessLauncherDelegate* delegate,
+ base::CommandLine* cmd_line,
+ int child_process_id) {
DCHECK(CalledOnValidThread());
#if defined(OS_ANDROID)
@@ -453,10 +447,6 @@ void ChildProcessLauncher::Launch(
DCHECK(process_type == switches::kGpuProcess ||
!cmd_line->HasSwitch(switches::kNoSandbox));
- // We need to close the client end of the IPC channel to reliably detect
- // child termination. We will close this fd after we create the child
- // process which is asynchronous on Android.
- base::ScopedFD ipcfd(delegate->TakeIpcFd().release());
#endif
mojo::edk::ScopedPlatformHandle server_handle;
mojo::edk::ScopedPlatformHandle client_handle;
@@ -480,9 +470,6 @@ void ChildProcessLauncher::Launch(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
child_process_id, delegate,
-#if defined(OS_ANDROID)
- base::Passed(&ipcfd),
-#endif
base::Passed(&client_handle), cmd_line));
}
@@ -527,7 +514,6 @@ void ChildProcessLauncher::DidLaunch(
mojo::edk::ScopedPlatformHandle server_handle,
ZygoteHandle zygote,
#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
base::ScopedFD mojo_fd,
#endif
base::Process process,
@@ -537,9 +523,6 @@ void ChildProcessLauncher::DidLaunch(
if (instance.get()) {
instance->Notify(zygote, std::move(server_handle),
-#if defined(OS_ANDROID)
- std::move(ipcfd),
-#endif
std::move(process), error_code);
} else {
if (process.IsValid() && terminate_on_shutdown) {
@@ -554,9 +537,6 @@ void ChildProcessLauncher::DidLaunch(
void ChildProcessLauncher::Notify(ZygoteHandle zygote,
mojo::edk::ScopedPlatformHandle server_handle,
-#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
-#endif
base::Process process,
int error_code) {
DCHECK(CalledOnValidThread());
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index b0cf02ca54e..c7646bd8450 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -7,6 +7,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
+#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
@@ -129,7 +130,6 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
mojo::edk::ScopedPlatformHandle server_handle,
ZygoteHandle zygote,
#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
base::ScopedFD mojo_fd,
#endif
base::Process process,
@@ -138,9 +138,6 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
// Notifies the client about the result of the operation.
void Notify(ZygoteHandle zygote,
mojo::edk::ScopedPlatformHandle server_handle,
-#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
-#endif
base::Process process,
int error_code);
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 40e54682a65..39864532a12 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -343,8 +343,8 @@ ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
RegisterPseudoScheme(url::kAboutScheme);
RegisterPseudoScheme(url::kJavaScriptScheme);
RegisterPseudoScheme(kViewSourceScheme);
- RegisterPseudoScheme(kHttpSuboriginScheme);
- RegisterPseudoScheme(kHttpsSuboriginScheme);
+ RegisterPseudoScheme(url::kHttpSuboriginScheme);
+ RegisterPseudoScheme(url::kHttpsSuboriginScheme);
}
ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
@@ -710,8 +710,8 @@ bool ChildProcessSecurityPolicyImpl::CanSetAsOriginHeader(int child_id,
return false; // Can't set invalid URLs as origin headers.
// Suborigin URLs are a special case and are allowed to be an origin header.
- if (url.scheme() == kHttpSuboriginScheme ||
- url.scheme() == kHttpsSuboriginScheme) {
+ if (url.scheme() == url::kHttpSuboriginScheme ||
+ url.scheme() == url::kHttpsSuboriginScheme) {
DCHECK(IsPseudoScheme(url.scheme()));
return true;
}
@@ -795,38 +795,38 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
int child_id,
- const storage::FileSystemURL& url,
+ const storage::FileSystemURL& filesystem_url,
int permissions) {
- if (!url.is_valid())
+ if (!filesystem_url.is_valid())
return false;
- // If |url.origin()| is not committable in this process, then this page
- // should not be able to place content in that origin via the filesystem
+ // If |filesystem_url.origin()| is not committable in this process, then this
+ // page should not be able to place content in that origin via the filesystem
// API either.
- if (!CanCommitURL(child_id, url.origin())) {
+ if (!CanCommitURL(child_id, filesystem_url.origin())) {
UMA_HISTOGRAM_BOOLEAN("FileSystem.OriginFailedCanCommitURL", true);
return false;
}
- if (url.path().ReferencesParent())
+ if (filesystem_url.path().ReferencesParent())
return false;
// Any write access is disallowed on the root path.
- if (storage::VirtualPath::IsRootPath(url.path()) &&
+ if (storage::VirtualPath::IsRootPath(filesystem_url.path()) &&
(permissions & ~READ_FILE_GRANT)) {
return false;
}
- if (url.mount_type() == storage::kFileSystemTypeIsolated) {
+ if (filesystem_url.mount_type() == storage::kFileSystemTypeIsolated) {
// When Isolated filesystems is overlayed on top of another filesystem,
// its per-filesystem permission overrides the underlying filesystem
// permissions).
return HasPermissionsForFileSystem(
- child_id, url.mount_filesystem_id(), permissions);
+ child_id, filesystem_url.mount_filesystem_id(), permissions);
}
FileSystemPermissionPolicyMap::iterator found =
- file_system_policy_map_.find(url.type());
+ file_system_policy_map_.find(filesystem_url.type());
if (found == file_system_policy_map_.end())
return false;
@@ -836,7 +836,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
}
if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
- return HasPermissionsForFile(child_id, url.path(), permissions);
+ return HasPermissionsForFile(child_id, filesystem_url.path(), permissions);
if (found->second & storage::FILE_PERMISSION_SANDBOX)
return true;
@@ -846,39 +846,44 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
+ READ_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
+ WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
+ CREATE_NEW_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url,
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
CREATE_READ_WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
+ COPY_INTO_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
int child_id,
- const storage::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
+ const storage::FileSystemURL& filesystem_url) {
+ return HasPermissionsForFileSystemFile(child_id, filesystem_url,
+ DELETE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index befca236dce..82f0e9be22c 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -139,14 +139,19 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
bool CanSetAsOriginHeader(int child_id, const GURL& url);
// Explicit permissions checks for FileSystemURL specified files.
- bool CanReadFileSystemFile(int child_id, const storage::FileSystemURL& url);
- bool CanWriteFileSystemFile(int child_id, const storage::FileSystemURL& url);
- bool CanCreateFileSystemFile(int child_id, const storage::FileSystemURL& url);
- bool CanCreateReadWriteFileSystemFile(int child_id,
- const storage::FileSystemURL& url);
+ bool CanReadFileSystemFile(int child_id,
+ const storage::FileSystemURL& filesystem_url);
+ bool CanWriteFileSystemFile(int child_id,
+ const storage::FileSystemURL& filesystem_url);
+ bool CanCreateFileSystemFile(int child_id,
+ const storage::FileSystemURL& filesystem_url);
+ bool CanCreateReadWriteFileSystemFile(
+ int child_id,
+ const storage::FileSystemURL& filesystem_url);
bool CanCopyIntoFileSystemFile(int child_id,
- const storage::FileSystemURL& url);
- bool CanDeleteFileSystemFile(int child_id, const storage::FileSystemURL& url);
+ const storage::FileSystemURL& filesystem_url);
+ bool CanDeleteFileSystemFile(int child_id,
+ const storage::FileSystemURL& filesystem_url);
// Returns true if the specified child_id has been granted ReadRawCookies.
bool CanReadRawCookies(int child_id);
@@ -216,9 +221,10 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Determines if certain permissions were granted for a file in FileSystem
// API. |permissions| is an internally defined bit-set.
- bool HasPermissionsForFileSystemFile(int child_id,
- const storage::FileSystemURL& url,
- int permissions);
+ bool HasPermissionsForFileSystemFile(
+ int child_id,
+ const storage::FileSystemURL& filesystem_url,
+ int permissions);
// Determines if certain permissions were granted for a file system.
// |permissions| is an internally defined bit-set.
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 43243488182..00138f23483 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -141,8 +141,8 @@ TEST_F(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) {
EXPECT_TRUE(p->IsPseudoScheme(url::kAboutScheme));
EXPECT_TRUE(p->IsPseudoScheme(url::kJavaScriptScheme));
EXPECT_TRUE(p->IsPseudoScheme(kViewSourceScheme));
- EXPECT_TRUE(p->IsPseudoScheme(kHttpSuboriginScheme));
- EXPECT_TRUE(p->IsPseudoScheme(kHttpsSuboriginScheme));
+ EXPECT_TRUE(p->IsPseudoScheme(url::kHttpSuboriginScheme));
+ EXPECT_TRUE(p->IsPseudoScheme(url::kHttpsSuboriginScheme));
EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme"));
p->RegisterPseudoScheme("registered-pseudo-scheme");
diff --git a/chromium/content/browser/compositor/OWNERS b/chromium/content/browser/compositor/OWNERS
index 44b33c441b6..1e10cf36001 100644
--- a/chromium/content/browser/compositor/OWNERS
+++ b/chromium/content/browser/compositor/OWNERS
@@ -1,3 +1,7 @@
danakj@chromium.org
jbauman@chromium.org
ccameron@chromium.org
+
+per-file *Mus*=fsamuel@chromium.org
+per-file *Mus*=sadrul@chromium.org
+per-file *Mus*=rjkroege@chromium.org
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index 2a017bf77bd..b93b865efe7 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -60,8 +60,6 @@ BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
void BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu(
base::TimeTicks timebase,
base::TimeDelta interval) {
- DCHECK(client_); // BindToClient should have been called already.
-
if (interval.is_zero()) {
// TODO(brianderson): We should not be receiving 0 intervals.
interval = cc::BeginFrameArgs::DefaultInterval();
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index 526ce4362f7..e049e4d1bb5 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -25,14 +25,8 @@ namespace gfx {
enum class SwapResult;
}
-namespace gpu {
-struct GpuProcessHostedCALayerTreeParamsMac;
-}
-
namespace content {
-class ContextProviderCommandBuffer;
class ReflectorImpl;
-class WebGraphicsContext3DCommandBufferImpl;
class CONTENT_EXPORT BrowserCompositorOutputSurface
: public cc::OutputSurface {
@@ -52,16 +46,6 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
// Called when |reflector_| was updated.
virtual void OnReflectorChanged();
- // Called when a swap completion is sent from the GPU process.
- // The argument |params_mac| is used to communicate parameters needed on Mac
- // to display the CALayer for the swap in the browser process.
- // TODO(ccameron): Remove |params_mac| when the CALayer tree is hosted in the
- // browser process.
- virtual void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) = 0;
-
#if defined(OS_MACOSX)
virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0;
#endif
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 73ca19860b1..5043c54d2b8 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -30,24 +30,22 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
std::move(vsync_manager),
begin_frame_source,
std::move(overlay_candidate_validator)),
- swap_buffers_completion_callback_(base::Bind(
- &GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
- base::Unretained(this))),
- update_vsync_parameters_callback_(base::Bind(
- &BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu,
- base::Unretained(this))) {}
+ weak_ptr_factory_(this) {
+ if (capabilities_.uses_default_gl_framebuffer) {
+ capabilities_.flipped_output_surface =
+ context_provider()->ContextCapabilities().flips_vertically;
+ }
+}
-GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
+GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() =
+ default;
-gpu::CommandBufferProxyImpl*
-GpuBrowserCompositorOutputSurface::GetCommandBufferProxy() {
- ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<content::ContextProviderCommandBuffer*>(
- context_provider_.get());
- gpu::CommandBufferProxyImpl* command_buffer_proxy =
- provider_command_buffer->GetCommandBufferProxy();
- DCHECK(command_buffer_proxy);
- return command_buffer_proxy;
+void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::SwapResult result,
+ const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
+ RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
+ client_->DidReceiveSwapBuffersAck();
}
void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
@@ -59,20 +57,18 @@ void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
}
}
-bool GpuBrowserCompositorOutputSurface::BindToClient(
+void GpuBrowserCompositorOutputSurface::BindToClient(
cc::OutputSurfaceClient* client) {
- if (!BrowserCompositorOutputSurface::BindToClient(client))
- return false;
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
- swap_buffers_completion_callback_.callback());
- GetCommandBufferProxy()->SetUpdateVSyncParametersCallback(
- update_vsync_parameters_callback_.callback());
- if (capabilities_.uses_default_gl_framebuffer) {
- capabilities_.flipped_output_surface =
- context_provider()->ContextCapabilities().flips_vertically;
- }
- return true;
+ base::Bind(&GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
+ GetCommandBufferProxy()->SetUpdateVSyncParametersCallback(base::Bind(
+ &GpuBrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu,
+ weak_ptr_factory_.GetWeakPtr()));
}
void GpuBrowserCompositorOutputSurface::EnsureBackbuffer() {}
@@ -85,6 +81,15 @@ void GpuBrowserCompositorOutputSurface::BindFramebuffer() {
context_provider()->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0);
}
+void GpuBrowserCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) {
+ context_provider()->ContextGL()->ResizeCHROMIUM(
+ size.width(), size.height(), device_scale_factor, has_alpha);
+}
+
void GpuBrowserCompositorOutputSurface::SwapBuffers(
cc::OutputSurfaceFrame frame) {
GetCommandBufferProxy()->SetLatencyInfo(frame.latency_info);
@@ -124,17 +129,20 @@ bool GpuBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle() const {
return false;
}
-void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
- client_->DidSwapBuffersComplete();
-}
-
#if defined(OS_MACOSX)
void GpuBrowserCompositorOutputSurface::SetSurfaceSuspendedForRecycle(
bool suspended) {}
#endif
+gpu::CommandBufferProxyImpl*
+GpuBrowserCompositorOutputSurface::GetCommandBufferProxy() {
+ ContextProviderCommandBuffer* provider_command_buffer =
+ static_cast<content::ContextProviderCommandBuffer*>(
+ context_provider_.get());
+ gpu::CommandBufferProxyImpl* command_buffer_proxy =
+ provider_command_buffer->GetCommandBufferProxy();
+ DCHECK(command_buffer_proxy);
+ return command_buffer_proxy;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
index 1f5f8d3944c..e567af3973a 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -7,8 +7,8 @@
#include <memory>
-#include "base/cancelable_callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "ui/gfx/swap_result.h"
@@ -19,13 +19,16 @@ class CompositorOverlayCandidateValidator;
namespace gpu {
class CommandBufferProxyImpl;
+struct GpuProcessHostedCALayerTreeParamsMac;
}
namespace ui {
class CompositorVSyncManager;
+class LatencyInfo;
}
namespace content {
+class ContextProviderCommandBuffer;
class ReflectorTexture;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
@@ -43,40 +46,43 @@ class GpuBrowserCompositorOutputSurface
~GpuBrowserCompositorOutputSurface() override;
- protected:
- // BrowserCompositorOutputSurface:
- void OnReflectorChanged() override;
- void OnGpuSwapBuffersCompleted(
+ // Called when a swap completion is sent from the GPU process.
+ // The argument |params_mac| is used to communicate parameters needed on Mac
+ // to display the CALayer for the swap in the browser process.
+ // TODO(ccameron): Remove |params_mac| when the CALayer tree is hosted in the
+ // browser process.
+ virtual void OnGpuSwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info,
gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
+ const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac);
+
+ // BrowserCompositorOutputSurface implementation.
+ void OnReflectorChanged() override;
#if defined(OS_MACOSX)
void SetSurfaceSuspendedForRecycle(bool suspended) override;
#endif
// cc::OutputSurface implementation.
- bool BindToClient(cc::OutputSurfaceClient* client) override;
+ void BindToClient(cc::OutputSurfaceClient* client) override;
void EnsureBackbuffer() override;
void DiscardBackbuffer() override;
void BindFramebuffer() override;
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) override;
void SwapBuffers(cc::OutputSurfaceFrame frame) override;
uint32_t GetFramebufferCopyTextureFormat() override;
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
bool SurfaceIsSuspendForRecycle() const override;
+ protected:
gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
- base::CancelableCallback<void(
- const std::vector<ui::LatencyInfo>&,
- gfx::SwapResult,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac)>
- swap_buffers_completion_callback_;
- base::CancelableCallback<void(base::TimeTicks timebase,
- base::TimeDelta interval)>
- update_vsync_parameters_callback_;
-
+ cc::OutputSurfaceClient* client_ = nullptr;
std::unique_ptr<ReflectorTexture> reflector_texture_;
+ base::WeakPtrFactory<GpuBrowserCompositorOutputSurface> weak_ptr_factory_;
private:
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.mm b/chromium/content/browser/compositor/gpu_output_surface_mac.mm
index 854af5b82b3..fda244489af 100644
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.mm
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.mm
@@ -7,7 +7,6 @@
#include "cc/output/output_surface_client.h"
#include "cc/output/output_surface_frame.h"
#include "components/display_compositor/compositor_overlay_candidate_validator.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h"
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 49d5d32d83d..7d1cf0c2d28 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -47,7 +47,7 @@
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/ipc/client/gpu_channel_host.h"
-#include "services/shell/runner/common/client_util.h"
+#include "services/service_manager/runner/common/client_util.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_constants.h"
@@ -59,6 +59,7 @@
#if defined(USE_AURA)
#include "content/browser/compositor/mus_browser_compositor_output_surface.h"
#include "content/public/common/service_manager_connection.h"
+#include "ui/aura/window_tree_host.h"
#endif
#if defined(OS_WIN)
@@ -85,7 +86,7 @@
#include "components/display_compositor/compositor_overlay_candidate_validator_android.h"
#endif
#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
-#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "gpu/ipc/common/gpu_surface_tracker.h"
#endif
#if defined(ENABLE_VULKAN)
@@ -100,7 +101,7 @@ namespace {
const int kNumRetriesBeforeSoftwareFallback = 4;
bool IsUsingMus() {
- return shell::ShellIsRemote();
+ return service_manager::ServiceManagerIsRemote();
}
scoped_refptr<content::ContextProviderCommandBuffer> CreateContextCommon(
@@ -196,7 +197,7 @@ std::unique_ptr<cc::SoftwareOutputDevice>
GpuProcessTransportFactory::CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
#if defined(USE_AURA)
- if (shell::ShellIsRemote()) {
+ if (service_manager::ServiceManagerIsRemote()) {
NOTREACHED();
return nullptr;
}
@@ -452,7 +453,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
if (vulkan_context_provider) {
vulkan_surface.reset(new VulkanBrowserCompositorOutputSurface(
vulkan_context_provider, compositor->vsync_manager(),
- compositor->task_runner().get()));
+ begin_frame_source.get()));
if (!vulkan_surface->Initialize(compositor.get()->widget())) {
vulkan_surface->Destroy();
vulkan_surface.reset();
@@ -467,7 +468,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
display_output_surface =
base::MakeUnique<SoftwareBrowserCompositorOutputSurface>(
CreateSoftwareOutputDevice(compositor.get()),
- compositor->vsync_manager(), begin_frame_source.get());
+ compositor->vsync_manager(), begin_frame_source.get(),
+ compositor->task_runner());
} else {
DCHECK(context_provider);
const auto& capabilities = context_provider->ContextCapabilities();
@@ -510,11 +512,24 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
begin_frame_source.get(), std::move(validator));
} else {
#if defined(USE_AURA)
- display_output_surface =
- base::MakeUnique<MusBrowserCompositorOutputSurface>(
- compositor->window(), context_provider,
- compositor->vsync_manager(), begin_frame_source.get(),
- std::move(validator));
+ if (compositor->window()) {
+ // TODO(mfomitchev): Remove this clause once we complete the switch
+ // to Aura-Mus.
+ display_output_surface =
+ base::MakeUnique<MusBrowserCompositorOutputSurface>(
+ compositor->window(), context_provider,
+ GetGpuMemoryBufferManager(), compositor->vsync_manager(),
+ begin_frame_source.get(), std::move(validator));
+ } else {
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(
+ compositor->widget());
+ display_output_surface =
+ base::MakeUnique<MusBrowserCompositorOutputSurface>(
+ host->window(), context_provider,
+ GetGpuMemoryBufferManager(), compositor->vsync_manager(),
+ begin_frame_source.get(), std::move(validator));
+ }
#else
NOTREACHED();
#endif
@@ -539,12 +554,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// The Display owns and uses the |display_output_surface| created above.
data->display = base::MakeUnique<cc::Display>(
- HostSharedBitmapManager::current(),
- GetGpuMemoryBufferManager(),
- compositor->GetRendererSettings(), std::move(begin_frame_source),
- std::move(display_output_surface), std::move(scheduler),
- base::MakeUnique<cc::TextureMailboxDeleter>(
- compositor->task_runner().get()));
+ HostSharedBitmapManager::current(), GetGpuMemoryBufferManager(),
+ compositor->GetRendererSettings(), compositor->frame_sink_id(),
+ std::move(begin_frame_source), std::move(display_output_surface),
+ std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(
+ compositor->task_runner().get()));
// The |delegated_output_surface| is given back to the compositor, it
// delegates to the Display as its root surface. Importantly, it shares the
@@ -559,7 +573,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
: base::MakeUnique<cc::DirectCompositorFrameSink>(
compositor->frame_sink_id(), surface_manager_.get(),
data->display.get(), context_provider,
- shared_worker_context_provider_);
+ shared_worker_context_provider_, GetGpuMemoryBufferManager(),
+ HostSharedBitmapManager::current());
data->display->Resize(compositor->size());
data->display->SetOutputIsSecure(data->output_is_secure);
compositor->SetCompositorFrameSink(std::move(compositor_frame_sink));
@@ -597,7 +612,7 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
DCHECK(data);
#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
if (data->surface_handle)
- GpuSurfaceTracker::Get()->RemoveSurface(data->surface_handle);
+ gpu::GpuSurfaceTracker::Get()->RemoveSurface(data->surface_handle);
#endif
per_compositor_data_.erase(it);
if (per_compositor_data_.empty()) {
@@ -611,8 +626,8 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
// If there are any observer left at this point, make sure they clean up
// before we destroy the GLHelper.
- FOR_EACH_OBSERVER(ui::ContextFactoryObserver, observer_list_,
- OnLostResources());
+ for (auto& observer : observer_list_)
+ observer.OnLostResources();
helper.reset();
DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
@@ -632,10 +647,6 @@ uint32_t GpuProcessTransportFactory::GetImageTextureTarget(
return BrowserGpuMemoryBufferManager::GetImageTextureTarget(format, usage);
}
-cc::SharedBitmapManager* GpuProcessTransportFactory::GetSharedBitmapManager() {
- return HostSharedBitmapManager::current();
-}
-
gpu::GpuMemoryBufferManager*
GpuProcessTransportFactory::GetGpuMemoryBufferManager() {
return gpu_channel_factory_->GetGpuMemoryBufferManager();
@@ -823,7 +834,7 @@ GpuProcessTransportFactory::CreatePerCompositorData(
#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
data->surface_handle = widget;
#else
- GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
+ gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
data->surface_handle = tracker->AddSurfaceForNativeWidget(widget);
#endif
}
@@ -854,8 +865,8 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
std::unique_ptr<display_compositor::GLHelper> lost_gl_helper =
std::move(gl_helper_);
- FOR_EACH_OBSERVER(ui::ContextFactoryObserver, observer_list_,
- OnLostResources());
+ for (auto& observer : observer_list_)
+ observer.OnLostResources();
// Kill things that use the shared context before killing the shared context.
lost_gl_helper.reset();
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index 74164396fb3..cf8d0409343 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -21,7 +21,6 @@
#include "ui/compositor/compositor.h"
namespace base {
-class SimpleThread;
class Thread;
}
@@ -33,12 +32,8 @@ class VulkanInProcessContextProvider;
}
namespace content {
-class BrowserCompositorOutputSurface;
-class CompositorSwapClient;
class ContextProviderCommandBuffer;
class OutputDeviceBacking;
-class ReflectorImpl;
-class WebGraphicsContext3DCommandBufferImpl;
class GpuProcessTransportFactory
: public ui::ContextFactory,
@@ -59,7 +54,6 @@ class GpuProcessTransportFactory
bool DoesCreateTestContexts() override;
uint32_t GetImageTextureTarget(gfx::BufferFormat format,
gfx::BufferUsage usage) override;
- cc::SharedBitmapManager* GetSharedBitmapManager() override;
gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
cc::TaskGraphRunner* GetTaskGraphRunner() override;
cc::FrameSinkId AllocateFrameSinkId() override;
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
index 2d61fa0f25d..2cec7abf66a 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -91,14 +91,14 @@ GLenum GpuSurfacelessBrowserCompositorOutputSurface::
void GpuSurfacelessBrowserCompositorOutputSurface::Reshape(
const gfx::Size& size,
- float scale_factor,
+ float device_scale_factor,
const gfx::ColorSpace& color_space,
- bool alpha) {
+ bool has_alpha) {
reshape_size_ = size;
- GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor, color_space,
- alpha);
+ GpuBrowserCompositorOutputSurface::Reshape(size, device_scale_factor,
+ color_space, has_alpha);
DCHECK(buffer_queue_);
- buffer_queue_->Reshape(size, scale_factor, color_space);
+ buffer_queue_->Reshape(size, device_scale_factor, color_space);
}
void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
index b4d750df188..87581ff3438 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -42,9 +42,9 @@ class GpuSurfacelessBrowserCompositorOutputSurface
void BindFramebuffer() override;
uint32_t GetFramebufferCopyTextureFormat() override;
void Reshape(const gfx::Size& size,
- float scale_factor,
+ float device_scale_factor,
const gfx::ColorSpace& color_space,
- bool alpha) override;
+ bool has_alpha) override;
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index aa6720575ea..7cd2574574f 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -21,15 +21,12 @@ class SurfaceManager;
}
namespace gfx {
-class Size;
enum class SwapResult;
}
namespace ui {
class Compositor;
class ContextFactory;
-class ContextFactoryObserver;
-class Texture;
}
namespace display_compositor {
diff --git a/chromium/content/browser/compositor/mus_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/mus_browser_compositor_output_surface.cc
index 6591e098858..acea5da8602 100644
--- a/chromium/content/browser/compositor/mus_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/mus_browser_compositor_output_surface.cc
@@ -15,13 +15,17 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "services/ui/public/cpp/window.h"
-#include "services/ui/public/cpp/window_surface.h"
+#include "services/ui/public/cpp/window_compositor_frame_sink.h"
+#include "ui/aura/mus/window_compositor_frame_sink.h"
+#include "ui/aura/mus/window_port_mus.h"
+#include "ui/aura/window.h"
namespace content {
MusBrowserCompositorOutputSurface::MusBrowserCompositorOutputSurface(
ui::Window* window,
scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
@@ -31,15 +35,39 @@ MusBrowserCompositorOutputSurface::MusBrowserCompositorOutputSurface(
begin_frame_source,
std::move(overlay_candidate_validator)),
ui_window_(window) {
- ui_window_surface_ =
- ui_window_->RequestSurface(ui::mojom::SurfaceType::DEFAULT);
+ ui_compositor_frame_sink_ = ui_window_->RequestCompositorFrameSink(
+ ui::mojom::CompositorFrameSinkType::DEFAULT, context,
+ gpu_memory_buffer_manager);
+ ui_compositor_frame_sink_->BindToClient(this);
+}
+
+MusBrowserCompositorOutputSurface::MusBrowserCompositorOutputSurface(
+ aura::Window* window,
+ scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
+ overlay_candidate_validator)
+ : GpuBrowserCompositorOutputSurface(std::move(context),
+ std::move(vsync_manager),
+ begin_frame_source,
+ std::move(overlay_candidate_validator)),
+ window_(window) {
+ aura::WindowPortMus* window_port = aura::WindowPortMus::Get(window_);
+ DCHECK(window_port);
+ compositor_frame_sink_ = window_port->RequestCompositorFrameSink(
+ ui::mojom::CompositorFrameSinkType::DEFAULT, context,
+ gpu_memory_buffer_manager);
+ compositor_frame_sink_->BindToClient(this);
}
MusBrowserCompositorOutputSurface::~MusBrowserCompositorOutputSurface() {}
void MusBrowserCompositorOutputSurface::SwapBuffers(
cc::OutputSurfaceFrame frame) {
- const gfx::Rect bounds(ui_window_->bounds().size());
+ const gfx::Rect bounds = ui_window_ ? gfx::Rect(ui_window_->bounds().size())
+ : gfx::Rect(window_->bounds().size());
cc::CompositorFrame ui_frame;
ui_frame.metadata.latency_info = std::move(frame.latency_info);
// Reset latency_info to known empty state after moving contents.
@@ -105,30 +133,21 @@ void MusBrowserCompositorOutputSurface::SwapBuffers(
secure_output_only);
ui_frame.delegated_frame_data->render_pass_list.push_back(std::move(pass));
- // ui_frame_surface_ will be destroyed by MusBrowserCompositorOutputSurface's
- // destructor, and the callback of SubmitCompositorFrame() will not be fired
- // after ui_window_surface_ is destroyed, so it is safe to use
- // base::Unretained(this) here.
- ui_window_surface_->SubmitCompositorFrame(
- std::move(ui_frame),
- base::Bind(&MusBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
- base::Unretained(this), std::vector<ui::LatencyInfo>(),
- gfx::SwapResult::SWAP_ACK, nullptr));
+
+ // TODO(mfomitchev): Remove ui_compositor_frame_sink_ once we complete the
+ // switch to Aura-Mus.
+ if (ui_compositor_frame_sink_)
+ ui_compositor_frame_sink_->SubmitCompositorFrame(std::move(ui_frame));
+ else
+ compositor_frame_sink_->SubmitCompositorFrame(std::move(ui_frame));
return;
}
-bool MusBrowserCompositorOutputSurface::BindToClient(
- cc::OutputSurfaceClient* client) {
- if (!GpuBrowserCompositorOutputSurface::BindToClient(client))
- return false;
- ui_window_surface_->BindToThread();
- ui_window_surface_->set_client(this);
- return true;
-}
+void MusBrowserCompositorOutputSurface::SetBeginFrameSource(
+ cc::BeginFrameSource* source) {}
-void MusBrowserCompositorOutputSurface::OnResourcesReturned(
- ui::WindowSurface* surface,
- mojo::Array<cc::ReturnedResource> resources) {
+void MusBrowserCompositorOutputSurface::ReclaimResources(
+ const cc::ReturnedResourceArray& resources) {
for (const auto& resource : resources) {
DCHECK_EQ(1, resource.count);
const gpu::Mailbox& mailbox = GetMailboxFromResourceId(resource.id);
@@ -138,6 +157,28 @@ void MusBrowserCompositorOutputSurface::OnResourcesReturned(
}
}
+void MusBrowserCompositorOutputSurface::SetTreeActivationCallback(
+ const base::Closure& callback) {}
+
+void MusBrowserCompositorOutputSurface::DidReceiveCompositorFrameAck() {
+ OnGpuSwapBuffersCompleted(std::vector<ui::LatencyInfo>(),
+ gfx::SwapResult::SWAP_ACK, nullptr);
+}
+
+void MusBrowserCompositorOutputSurface::DidLoseCompositorFrameSink() {}
+
+void MusBrowserCompositorOutputSurface::OnDraw(
+ const gfx::Transform& transform,
+ const gfx::Rect& viewport,
+ bool resourceless_software_draw) {}
+
+void MusBrowserCompositorOutputSurface::SetMemoryPolicy(
+ const cc::ManagedMemoryPolicy& policy) {}
+
+void MusBrowserCompositorOutputSurface::SetExternalTilePriorityConstraints(
+ const gfx::Rect& viewport_rect,
+ const gfx::Transform& transform) {}
+
uint32_t MusBrowserCompositorOutputSurface::AllocateResourceId() {
if (!free_resource_ids_.empty()) {
uint32_t id = free_resource_ids_.back();
diff --git a/chromium/content/browser/compositor/mus_browser_compositor_output_surface.h b/chromium/content/browser/compositor/mus_browser_compositor_output_surface.h
index 31346f88022..476f4524b86 100644
--- a/chromium/content/browser/compositor/mus_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/mus_browser_compositor_output_surface.h
@@ -9,14 +9,24 @@
#include <vector>
#include "base/macros.h"
+#include "cc/output/compositor_frame_sink_client.h"
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/ipc/common/surface_handle.h"
-#include "services/ui/public/cpp/window_surface_client.h"
+namespace aura {
+class Window;
+class WindowCompositorFrameSink;
+}
+
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
+// TODO(mfomitchev): Remove once we complete the switch to Aura-Mus.
namespace ui {
class Window;
-class WindowSurface;
+class WindowCompositorFrameSink;
}
namespace content {
@@ -26,11 +36,23 @@ namespace content {
// arriving from the GPU process.
class MusBrowserCompositorOutputSurface
: public GpuBrowserCompositorOutputSurface,
- public ui::WindowSurfaceClient {
+ public cc::CompositorFrameSinkClient {
public:
+ // TODO(mfomitchev): Remove this constructor once we complete the switch to
+ // Aura-Mus.
MusBrowserCompositorOutputSurface(
ui::Window* window,
scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
+ overlay_candidate_validator);
+
+ MusBrowserCompositorOutputSurface(
+ aura::Window* window,
+ scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
@@ -41,20 +63,32 @@ class MusBrowserCompositorOutputSurface
protected:
// cc::OutputSurface implementation.
void SwapBuffers(cc::OutputSurfaceFrame frame) override;
- bool BindToClient(cc::OutputSurfaceClient* client) override;
- // ui::WindowSurfaceClient:
- void OnResourcesReturned(
- ui::WindowSurface* surface,
- mojo::Array<cc::ReturnedResource> resources) override;
+ // cc::CompositorFrameSinkClient:
+ void SetBeginFrameSource(cc::BeginFrameSource* source) override;
+ void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
+ void SetTreeActivationCallback(const base::Closure& callback) override;
+ void DidReceiveCompositorFrameAck() override;
+ void DidLoseCompositorFrameSink() override;
+ void OnDraw(const gfx::Transform& transform,
+ const gfx::Rect& viewport,
+ bool resourceless_software_draw) override;
+ void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override;
+ void SetExternalTilePriorityConstraints(
+ const gfx::Rect& viewport_rect,
+ const gfx::Transform& transform) override;
private:
uint32_t AllocateResourceId();
void FreeResourceId(uint32_t id);
const gpu::Mailbox& GetMailboxFromResourceId(uint32_t id);
+ // TODO(mfomitchev): Remove once we complete the switch to Aura-Mus.
ui::Window* ui_window_;
- std::unique_ptr<ui::WindowSurface> ui_window_surface_;
+ std::unique_ptr<ui::WindowCompositorFrameSink> ui_compositor_frame_sink_;
+
+ aura::Window* window_;
+ std::unique_ptr<aura::WindowCompositorFrameSink> compositor_frame_sink_;
std::vector<uint32_t> free_resource_ids_;
std::vector<gpu::Mailbox> mailboxes_;
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
index aa2df8f0c4a..a43de0d4d67 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -47,6 +47,13 @@ OffscreenBrowserCompositorOutputSurface::
DiscardBackbuffer();
}
+void OffscreenBrowserCompositorOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
+}
+
void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
bool update_source_texture = !reflector_texture_ || reflector_changed_;
reflector_changed_ = false;
@@ -57,8 +64,8 @@ void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
const int max_texture_size =
context_provider_->ContextCapabilities().max_texture_size;
- int texture_width = std::min(max_texture_size, surface_size_.width());
- int texture_height = std::min(max_texture_size, surface_size_.height());
+ int texture_width = std::min(max_texture_size, reshape_size_.width());
+ int texture_height = std::min(max_texture_size, reshape_size_.height());
gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id());
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -107,11 +114,7 @@ void OffscreenBrowserCompositorOutputSurface::Reshape(
float scale_factor,
const gfx::ColorSpace& color_space,
bool alpha) {
- if (size == surface_size_)
- return;
-
- surface_size_ = size;
- device_scale_factor_ = scale_factor;
+ reshape_size_ = size;
DiscardBackbuffer();
EnsureBackbuffer();
}
@@ -132,7 +135,7 @@ void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() {
void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
cc::OutputSurfaceFrame frame) {
gfx::Size surface_size = frame.size;
- DCHECK(surface_size == surface_size_);
+ DCHECK(surface_size == reshape_size_);
gfx::Rect swap_rect = frame.sub_buffer_rect;
if (reflector_) {
@@ -185,7 +188,7 @@ void OffscreenBrowserCompositorOutputSurface::OnReflectorChanged() {
}
void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete() {
- client_->DidSwapBuffersComplete();
+ client_->DidReceiveSwapBuffersAck();
}
} // namespace content
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
index 95d6a55251d..983f5d3fe7d 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -20,7 +20,7 @@ class CompositorVSyncManager;
}
namespace content {
-class CommandBufferProxyImpl;
+class ContextProviderCommandBuffer;
class ReflectorTexture;
class OffscreenBrowserCompositorOutputSurface
@@ -35,8 +35,9 @@ class OffscreenBrowserCompositorOutputSurface
~OffscreenBrowserCompositorOutputSurface() override;
- protected:
- // cc::OutputSurface:
+ private:
+ // cc::OutputSurface implementation.
+ void BindToClient(cc::OutputSurfaceClient* client) override;
void EnsureBackbuffer() override;
void DiscardBackbuffer() override;
void Reshape(const gfx::Size& size,
@@ -50,26 +51,22 @@ class OffscreenBrowserCompositorOutputSurface
bool SurfaceIsSuspendForRecycle() const override;
uint32_t GetFramebufferCopyTextureFormat() override;
- // BrowserCompositorOutputSurface
+ // BrowserCompositorOutputSurface implementation.
void OnReflectorChanged() override;
- void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override{};
#if defined(OS_MACOSX)
void SetSurfaceSuspendedForRecycle(bool suspended) override {};
#endif
+ void OnSwapBuffersComplete();
+
+ cc::OutputSurfaceClient* client_ = nullptr;
+ gfx::Size reshape_size_;
uint32_t fbo_ = 0;
bool reflector_changed_ = false;
std::unique_ptr<ReflectorTexture> reflector_texture_;
-
base::WeakPtrFactory<OffscreenBrowserCompositorOutputSurface>
weak_ptr_factory_;
- private:
- void OnSwapBuffersComplete();
-
DISALLOW_COPY_AND_ASSIGN(OffscreenBrowserCompositorOutputSurface);
};
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index e57bb02c8e1..8d8d6bc04dd 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -9,7 +9,6 @@
#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 "cc/test/test_context_provider.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "components/display_compositor/compositor_overlay_candidate_validator.h"
@@ -84,14 +83,18 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
std::move(vsync_manager),
begin_frame_source,
CreateTestValidatorOzone()) {
- device_scale_factor_ = 1.f;
}
void SetFlip(bool flip) { capabilities_.flipped_output_surface = flip; }
+ void BindToClient(cc::OutputSurfaceClient* client) override {}
void EnsureBackbuffer() override {}
void DiscardBackbuffer() override {}
void BindFramebuffer() override {}
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) override {}
void SwapBuffers(cc::OutputSurfaceFrame frame) override {}
uint32_t GetFramebufferCopyTextureFormat() override { return GL_RGB; }
bool IsDisplayedAsOverlayPlane() const override { return false; }
@@ -107,13 +110,6 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
}
}
- void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override {
- NOTREACHED();
- }
-
#if defined(OS_MACOSX)
void SetSurfaceSuspendedForRecycle(bool suspended) override {}
#endif
@@ -145,10 +141,12 @@ class ReflectorImplTest : public testing::Test {
compositor_.reset(
new ui::Compositor(context_factory, compositor_task_runner_.get()));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
+
+ auto context_provider = cc::TestContextProvider::Create();
+ context_provider->BindToCurrentThread();
output_surface_ = base::MakeUnique<TestOutputSurface>(
- cc::TestContextProvider::Create(cc::TestWebGraphicsContext3D::Create()),
- compositor_->vsync_manager(), begin_frame_source_.get());
- CHECK(output_surface_->BindToClient(&output_surface_client_));
+ std::move(context_provider), compositor_->vsync_manager(),
+ begin_frame_source_.get());
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
compositor_->SetRootLayer(root_layer_.get());
@@ -184,7 +182,6 @@ class ReflectorImplTest : public testing::Test {
protected:
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
std::unique_ptr<cc::SyntheticBeginFrameSource> begin_frame_source_;
- cc::FakeOutputSurfaceClient output_surface_client_;
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 4e80d5bf99c..4e6fd5f83a5 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -23,16 +24,25 @@ namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- cc::SyntheticBeginFrameSource* begin_frame_source)
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: BrowserCompositorOutputSurface(std::move(software_device),
vsync_manager,
begin_frame_source),
+ task_runner_(std::move(task_runner)),
weak_factory_(this) {}
SoftwareBrowserCompositorOutputSurface::
~SoftwareBrowserCompositorOutputSurface() {
}
+void SoftwareBrowserCompositorOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
+}
+
void SoftwareBrowserCompositorOutputSurface::EnsureBackbuffer() {
software_device()->EnsureBackbuffer();
}
@@ -46,8 +56,17 @@ void SoftwareBrowserCompositorOutputSurface::BindFramebuffer() {
NOTREACHED();
}
+void SoftwareBrowserCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) {
+ software_device()->Resize(size, device_scale_factor);
+}
+
void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
cc::OutputSurfaceFrame frame) {
+ DCHECK(client_);
base::TimeTicks swap_time = base::TimeTicks::Now();
for (auto& latency : frame.latency_info) {
latency.AddLatencyNumberWithTimestamp(
@@ -56,9 +75,9 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
swap_time, 1);
}
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&RenderWidgetHostImpl::CompositorFrameDrawn,
- frame.latency_info));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&RenderWidgetHostImpl::CompositorFrameDrawn,
+ frame.latency_info));
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
if (vsync_provider) {
@@ -66,7 +85,15 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
&BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu,
weak_factory_.GetWeakPtr()));
}
- PostSwapBuffersComplete();
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
+ weak_factory_.GetWeakPtr()));
+}
+
+void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback() {
+ client_->DidReceiveSwapBuffersAck();
}
bool SoftwareBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane() const {
@@ -89,13 +116,6 @@ SoftwareBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
return 0;
}
-void SoftwareBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
- NOTREACHED();
-}
-
#if defined(OS_MACOSX)
void SoftwareBrowserCompositorOutputSurface::SetSurfaceSuspendedForRecycle(
bool suspended) {
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
index 0647e3080d7..7fc5a6b1092 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -27,14 +27,20 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- cc::SyntheticBeginFrameSource* begin_frame_source);
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~SoftwareBrowserCompositorOutputSurface() override;
// OutputSurface implementation.
+ void BindToClient(cc::OutputSurfaceClient* client) override;
void EnsureBackbuffer() override;
void DiscardBackbuffer() override;
void BindFramebuffer() override;
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) override;
void SwapBuffers(cc::OutputSurfaceFrame frame) override;
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
@@ -43,15 +49,14 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
private:
// BrowserCompositorOutputSurface implementation.
- void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
-
#if defined(OS_MACOSX)
void SetSurfaceSuspendedForRecycle(bool suspended) override;
#endif
+ void SwapBuffersCallback();
+
+ cc::OutputSurfaceClient* client_ = nullptr;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<SoftwareBrowserCompositorOutputSurface> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurface);
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index 0ee0fa93381..a91c8326a45 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
@@ -109,7 +109,8 @@ std::unique_ptr<content::BrowserCompositorOutputSurface>
SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
std::unique_ptr<cc::SoftwareOutputDevice> device) {
return base::MakeUnique<content::SoftwareBrowserCompositorOutputSurface>(
- std::move(device), compositor_->vsync_manager(), &begin_frame_source_);
+ std::move(device), compositor_->vsync_manager(), &begin_frame_source_,
+ base::ThreadTaskRunnerHandle::Get());
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
@@ -117,7 +118,7 @@ TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
std::unique_ptr<cc::SoftwareOutputDevice> software_device(
new cc::SoftwareOutputDevice());
output_surface_ = CreateSurface(std::move(software_device));
- CHECK(output_surface_->BindToClient(&output_surface_client));
+ output_surface_->BindToClient(&output_surface_client);
output_surface_->SwapBuffers(cc::OutputSurfaceFrame());
EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider());
@@ -128,7 +129,7 @@ TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
std::unique_ptr<cc::SoftwareOutputDevice> software_device(
new FakeSoftwareOutputDevice());
output_surface_ = CreateSurface(std::move(software_device));
- CHECK(output_surface_->BindToClient(&output_surface_client));
+ output_surface_->BindToClient(&output_surface_client);
FakeVSyncProvider* vsync_provider = static_cast<FakeVSyncProvider*>(
output_surface_->software_device()->GetVSyncProvider());
diff --git a/chromium/content/browser/compositor/software_output_device_ozone.cc b/chromium/content/browser/compositor/software_output_device_ozone.cc
index c65cda5dc19..da854ec419d 100644
--- a/chromium/content/browser/compositor/software_output_device_ozone.cc
+++ b/chromium/content/browser/compositor/software_output_device_ozone.cc
@@ -45,8 +45,6 @@ SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() {
void SoftwareOutputDeviceOzone::Resize(const gfx::Size& viewport_pixel_size,
float scale_factor) {
- scale_factor_ = scale_factor;
-
if (viewport_pixel_size_ == viewport_pixel_size)
return;
diff --git a/chromium/content/browser/compositor/software_output_device_win.cc b/chromium/content/browser/compositor/software_output_device_win.cc
index 3ab7677a543..c48bed4fa0e 100644
--- a/chromium/content/browser/compositor/software_output_device_win.cc
+++ b/chromium/content/browser/compositor/software_output_device_win.cc
@@ -114,8 +114,6 @@ void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!in_paint_);
- scale_factor_ = scale_factor;
-
if (viewport_pixel_size_ == viewport_pixel_size)
return;
@@ -181,7 +179,7 @@ void SoftwareOutputDeviceWin::EndPaint() {
SetWindowLong(hwnd_, GWL_EXSTYLE, style);
skia::ScopedPlatformPaint spp(contents_.get());
- HDC dib_dc = spp.GetPlatformSurface();
+ HDC dib_dc = spp.GetNativeDrawingContext();
::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero,
RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
} else {
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
index b06f9f22ab6..da97d274591 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -11,12 +11,13 @@
namespace content {
VulkanBrowserCompositorOutputSurface::VulkanBrowserCompositorOutputSurface(
- const scoped_refptr<cc::VulkanContextProvider>& context,
- const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
+ scoped_refptr<cc::VulkanContextProvider> context,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
cc::SyntheticBeginFrameSource* begin_frame_source)
- : BrowserCompositorOutputSurface(context,
- vsync_manager,
- begin_frame_source) {}
+ : BrowserCompositorOutputSurface(std::move(context),
+ std::move(vsync_manager),
+ begin_frame_source),
+ weak_ptr_factory_(this) {}
VulkanBrowserCompositorOutputSurface::~VulkanBrowserCompositorOutputSurface() {
Destroy();
@@ -43,18 +44,67 @@ void VulkanBrowserCompositorOutputSurface::Destroy() {
}
}
-void VulkanBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
- OnSwapBuffersComplete();
+void VulkanBrowserCompositorOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
+}
+
+void VulkanBrowserCompositorOutputSurface::EnsureBackbuffer() {
+ NOTIMPLEMENTED();
+}
+
+void VulkanBrowserCompositorOutputSurface::DiscardBackbuffer() {
+ NOTIMPLEMENTED();
+}
+
+void VulkanBrowserCompositorOutputSurface::BindFramebuffer() {
+ NOTIMPLEMENTED();
+}
+
+bool VulkanBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+unsigned VulkanBrowserCompositorOutputSurface::GetOverlayTextureId() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool VulkanBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void VulkanBrowserCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) {
+ NOTIMPLEMENTED();
+}
+
+uint32_t
+VulkanBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ NOTIMPLEMENTED();
+ return 0;
}
void VulkanBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
+ cc::OutputSurfaceFrame frame) {
surface_->SwapBuffers();
- PostSwapBuffersComplete();
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&VulkanBrowserCompositorOutputSurface::SwapBuffersAck,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void VulkanBrowserCompositorOutputSurface::SwapBuffersAck() {
+ DCHECK(client_);
+ client_->DidReceiveSwapBuffersAck();
}
} // namespace content
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
index ed53ac0b1b2..c2abaa1df08 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
@@ -8,6 +8,8 @@
#include <memory>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "cc/output/output_surface_frame.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "ui/gfx/native_widget_types.h"
@@ -21,8 +23,8 @@ class VulkanBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
VulkanBrowserCompositorOutputSurface(
- const scoped_refptr<cc::VulkanContextProvider>& context,
- const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
+ scoped_refptr<cc::VulkanContextProvider> context,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
cc::SyntheticBeginFrameSource* begin_frame_source);
~VulkanBrowserCompositorOutputSurface() override;
@@ -30,18 +32,27 @@ class VulkanBrowserCompositorOutputSurface
bool Initialize(gfx::AcceleratedWidget widget);
void Destroy();
- // BrowserCompositorOutputSurface implementation.
- void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
-
- protected:
// cc::OutputSurface implementation.
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void BindToClient(cc::OutputSurfaceClient* client) override;
+ void EnsureBackbuffer() override;
+ void DiscardBackbuffer() override;
+ void BindFramebuffer() override;
+ bool IsDisplayedAsOverlayPlane() const override;
+ unsigned GetOverlayTextureId() const override;
+ bool SurfaceIsSuspendForRecycle() const override;
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+ void SwapBuffers(cc::OutputSurfaceFrame frame) override;
private:
+ void SwapBuffersAck();
+
std::unique_ptr<gpu::VulkanSurface> surface_;
+ cc::OutputSurfaceClient* client_ = nullptr;
+ base::WeakPtrFactory<VulkanBrowserCompositorOutputSurface> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VulkanBrowserCompositorOutputSurface);
};
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index 9fc91a588a1..6711ca5ad0d 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -176,8 +176,8 @@ class CrossSiteTransferTest : public ContentBrowserTest {
base::Bind(&CrossSiteTransferTest::InjectResourceDispatcherHostDelegate,
base::Unretained(this)));
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
void TearDownOnMainThread() override {
diff --git a/chromium/content/browser/device_sensors/DEPS b/chromium/content/browser/device_sensors/DEPS
index e118614c16a..fac77c68906 100644
--- a/chromium/content/browser/device_sensors/DEPS
+++ b/chromium/content/browser/device_sensors/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+device/sensors/public/cpp",
"+third_party/sudden_motion_sensor",
]
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h b/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
index 85afac4b30d..6b209ae289e 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
@@ -10,9 +10,9 @@
#include "content/browser/device_sensors/data_fetcher_shared_memory_base.h"
#if !defined(OS_ANDROID)
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
#endif
#if defined(OS_MACOSX)
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
index d746b4d3285..3109f2104f4 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
@@ -6,9 +6,9 @@
#include "base/logging.h"
#include "content/browser/device_sensors/sensor_manager_android.h"
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
namespace content {
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
index b7694458518..34191f802de 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
@@ -15,9 +15,9 @@
#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
namespace content {
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
index fdb29581ffe..54e76be43b3 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
@@ -10,9 +10,9 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
index 15bde3362a0..ab455aa6949 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
@@ -10,33 +10,13 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "content/browser/device_sensors/ambient_light_mac.h"
+#include "device/sensors/public/cpp/device_util_mac.h"
#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
namespace {
const double kMeanGravity = 9.80665;
-double LMUvalueToLux(uint64_t raw_value) {
- // Conversion formula from regression.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=793728
- // Let x = raw_value, then
- // lux = -2.978303814*(10^-27)*x^4 + 2.635687683*(10^-19)*x^3 -
- // 3.459747434*(10^-12)*x^2 + 3.905829689*(10^-5)*x - 0.1932594532
-
- static const long double k4 = pow(10.L, -7);
- static const long double k3 = pow(10.L, -4);
- static const long double k2 = pow(10.L, -2);
- static const long double k1 = pow(10.L, 5);
- long double scaled_value = raw_value / k1;
-
- long double lux_value =
- (-3 * k4 * pow(scaled_value, 4)) + (2.6 * k3 * pow(scaled_value, 3)) +
- (-3.4 * k2 * pow(scaled_value, 2)) + (3.9 * scaled_value) - 0.19;
-
- double lux = ceil(static_cast<double>(lux_value));
- return lux > 0 ? lux : 0;
-}
-
void FetchLight(content::AmbientLightSensor* sensor,
content::DeviceLightHardwareBuffer* buffer) {
DCHECK(sensor);
@@ -48,7 +28,7 @@ void FetchLight(content::AmbientLightSensor* sensor,
if (!sensor->ReadSensorValue(lux_value))
return;
uint64_t mean = (lux_value[0] + lux_value[1]) / 2;
- double lux = LMUvalueToLux(mean);
+ double lux = device::LMUvalueToLux(mean);
buffer->seqlock.WriteBegin();
buffer->data.value = lux;
buffer->seqlock.WriteEnd();
diff --git a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
index b9f01ab48d3..5dafe9638dc 100644
--- a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -9,9 +9,6 @@
#include "build/build_config.h"
#include "content/browser/device_sensors/data_fetcher_shared_memory.h"
#include "content/browser/device_sensors/device_sensor_service.h"
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
@@ -21,6 +18,9 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_javascript_dialog_manager.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
namespace content {
@@ -28,22 +28,35 @@ namespace {
class FakeDataFetcher : public DataFetcherSharedMemory {
public:
- FakeDataFetcher()
- : started_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- stopped_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- started_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- stopped_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- started_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- stopped_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- sensor_data_available_(true) {}
+ 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 SetLightStartedCallback(base::Closure light_started_callback) {
+ light_started_callback_ = light_started_callback;
+ }
+
+ void SetLightStoppedCallback(base::Closure light_stopped_callback) {
+ light_stopped_callback_ = light_stopped_callback;
+ }
+
+ void SetOrientationStartedCallback(
+ base::Closure orientation_started_callback) {
+ orientation_started_callback_ = orientation_started_callback;
+ }
+
+ void SetOrientationStoppedCallback(
+ base::Closure orientation_stopped_callback) {
+ orientation_stopped_callback_ = orientation_stopped_callback;
+ }
+
bool Start(ConsumerType consumer_type, void* buffer) override {
EXPECT_TRUE(buffer);
@@ -54,7 +67,8 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
if (sensor_data_available_)
UpdateMotion(motion_buffer);
SetMotionBufferReady(motion_buffer);
- started_motion_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ motion_started_callback_);
} break;
case CONSUMER_TYPE_ORIENTATION: {
DeviceOrientationHardwareBuffer* orientation_buffer =
@@ -62,7 +76,8 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
if (sensor_data_available_)
UpdateOrientation(orientation_buffer);
SetOrientationBufferReady(orientation_buffer);
- started_orientation_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ orientation_started_callback_);
} break;
case CONSUMER_TYPE_LIGHT: {
DeviceLightHardwareBuffer* light_buffer =
@@ -71,7 +86,8 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
sensor_data_available_
? 100
: std::numeric_limits<double>::infinity());
- started_light_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ light_started_callback_);
} break;
default:
return false;
@@ -82,13 +98,16 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
bool Stop(ConsumerType consumer_type) override {
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
- stopped_motion_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ motion_stopped_callback_);
break;
case CONSUMER_TYPE_ORIENTATION:
- stopped_orientation_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ orientation_stopped_callback_);
break;
case CONSUMER_TYPE_LIGHT:
- stopped_light_.Signal();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ light_stopped_callback_);
break;
default:
return false;
@@ -164,12 +183,13 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
buffer->seqlock.WriteEnd();
}
- base::WaitableEvent started_orientation_;
- base::WaitableEvent stopped_orientation_;
- base::WaitableEvent started_motion_;
- base::WaitableEvent stopped_motion_;
- base::WaitableEvent started_light_;
- base::WaitableEvent stopped_light_;
+ // The below callbacks should be run on the UI thread.
+ base::Closure motion_started_callback_;
+ base::Closure orientation_started_callback_;
+ base::Closure light_started_callback_;
+ base::Closure motion_stopped_callback_;
+ base::Closure orientation_stopped_callback_;
+ base::Closure light_stopped_callback_;
bool sensor_data_available_;
private:
@@ -185,16 +205,41 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
base::WaitableEvent::InitialState::NOT_SIGNALED) {}
void SetUpOnMainThread() override {
+ // Initialize the RunLoops now that the main thread has been created.
+ light_started_runloop_.reset(new base::RunLoop());
+ light_stopped_runloop_.reset(new base::RunLoop());
+ 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());
+#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.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&DeviceSensorBrowserTest::SetUpOnIOThread,
base::Unretained(this)));
io_loop_finished_event_.Wait();
+#endif
}
- void SetUpOnIOThread() {
+ void SetUpFetcher() {
fetcher_ = new FakeDataFetcher();
+ fetcher_->SetLightStartedCallback(light_started_runloop_->QuitClosure());
+ fetcher_->SetLightStoppedCallback(light_stopped_runloop_->QuitClosure());
+ fetcher_->SetMotionStartedCallback(motion_started_runloop_->QuitClosure());
+ fetcher_->SetMotionStoppedCallback(motion_stopped_runloop_->QuitClosure());
+ fetcher_->SetOrientationStartedCallback(
+ orientation_started_runloop_->QuitClosure());
+ fetcher_->SetOrientationStoppedCallback(
+ orientation_stopped_runloop_->QuitClosure());
DeviceSensorService::GetInstance()->SetDataFetcherForTesting(fetcher_);
+ }
+
+ void SetUpOnIOThread() {
+ SetUpFetcher();
io_loop_finished_event_.Signal();
}
@@ -224,6 +269,15 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
FakeDataFetcher* fetcher_;
+ // 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> light_started_runloop_;
+ std::unique_ptr<base::RunLoop> light_stopped_runloop_;
+ 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_;
+
private:
base::WaitableEvent io_loop_finished_event_;
};
@@ -236,8 +290,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_orientation_.Wait();
- fetcher_->stopped_orientation_.Wait();
+ orientation_started_runloop_->Run();
+ orientation_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, LightTest) {
@@ -249,8 +303,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, LightTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_light_.Wait();
- fetcher_->stopped_light_.Wait();
+ light_started_runloop_->Run();
+ light_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionTest) {
@@ -261,8 +315,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_motion_.Wait();
- fetcher_->stopped_motion_.Wait();
+ motion_started_runloop_->Run();
+ motion_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, LightOneOffInfintyTest) {
@@ -276,8 +330,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, LightOneOffInfintyTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_light_.Wait();
- fetcher_->stopped_light_.Wait();
+ light_started_runloop_->Run();
+ light_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationNullTest) {
@@ -290,8 +344,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationNullTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_orientation_.Wait();
- fetcher_->stopped_orientation_.Wait();
+ orientation_started_runloop_->Run();
+ orientation_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionNullTest) {
@@ -303,15 +357,15 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionNullTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- fetcher_->started_motion_.Wait();
- fetcher_->stopped_motion_.Wait();
+ motion_started_runloop_->Run();
+ motion_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, NullTestWithAlert) {
- // The test page registers an event handlers for motion/orientation events
- // and expects to get events with null values. The test raises a modal alert
- // dialog with a delay to test that the one-off null-events still propagate
- // to window after the alert is dismissed and the callbacks are invoked which
+ // The test page registers an event handlers for motion/orientation events and
+ // expects to get events with null values. The test raises a modal alert
+ // dialog with a delay to test that the one-off null-events still propagate to
+ // window after the alert is dismissed and the callbacks are invoked which
// eventually navigate to #pass.
fetcher_->SetSensorDataAvailable(false);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
@@ -324,10 +378,10 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, NullTestWithAlert) {
// delay, crbug.com/360044.
WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(500));
- fetcher_->started_motion_.Wait();
- fetcher_->stopped_motion_.Wait();
- fetcher_->started_orientation_.Wait();
- fetcher_->stopped_orientation_.Wait();
+ motion_started_runloop_->Run();
+ motion_stopped_runloop_->Run();
+ orientation_started_runloop_->Run();
+ orientation_stopped_runloop_->Run();
same_tab_observer.Wait();
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
diff --git a/chromium/content/browser/device_sensors/device_sensor_host.cc b/chromium/content/browser/device_sensors/device_sensor_host.cc
index e4b806967e5..76096def5fb 100644
--- a/chromium/content/browser/device_sensors/device_sensor_host.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_host.cc
@@ -4,8 +4,8 @@
#include "content/browser/device_sensors/device_sensor_host.h"
+#include "base/message_loop/message_loop.h"
#include "content/browser/device_sensors/device_sensor_service.h"
-#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
@@ -21,7 +21,11 @@ void DeviceSensorHost<MojoInterface, consumer_type>::Create(
template <typename MojoInterface, ConsumerType consumer_type>
DeviceSensorHost<MojoInterface, consumer_type>::DeviceSensorHost()
: is_started_(false) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+#if defined(OS_ANDROID)
+ DCHECK(base::MessageLoopForUI::IsCurrent());
+#else
+ DCHECK(base::MessageLoopForIO::IsCurrent());
+#endif
}
template <typename MojoInterface, ConsumerType consumer_type>
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android.cc b/chromium/content/browser/device_sensors/sensor_manager_android.cc
index 22b416997b4..65f5771148e 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_android.cc
@@ -10,8 +10,8 @@
#include "base/android/jni_android.h"
#include "base/bind.h"
#include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
-#include "content/public/browser/browser_thread.h"
#include "jni/DeviceSensors_jni.h"
using base::android::AttachCurrentThread;
@@ -58,6 +58,7 @@ SensorManagerAndroid::SensorManagerAndroid()
motion_buffer_initialized_(false),
orientation_buffer_initialized_(false),
is_shutdown_(false) {
+ DCHECK(thread_checker_.CalledOnValidThread());
memset(received_motion_data_, 0, sizeof(received_motion_data_));
device_sensors_.Reset(Java_DeviceSensors_getInstance(
AttachCurrentThread(), base::android::GetApplicationContext()));
@@ -71,6 +72,7 @@ bool SensorManagerAndroid::Register(JNIEnv* env) {
}
SensorManagerAndroid* SensorManagerAndroid::GetInstance() {
+ DCHECK(base::MessageLoopForUI::IsCurrent());
return base::Singleton<
SensorManagerAndroid,
base::LeakySingletonTraits<SensorManagerAndroid>>::get();
@@ -207,6 +209,7 @@ void SensorManagerAndroid::GotLight(JNIEnv*,
}
bool SensorManagerAndroid::Start(ConsumerType consumer_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!device_sensors_.is_null());
int rate_in_microseconds = (consumer_type == CONSUMER_TYPE_LIGHT)
? kLightSensorIntervalMicroseconds
@@ -217,12 +220,14 @@ bool SensorManagerAndroid::Start(ConsumerType consumer_type) {
}
void SensorManagerAndroid::Stop(ConsumerType consumer_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!device_sensors_.is_null());
Java_DeviceSensors_stop(AttachCurrentThread(), device_sensors_,
static_cast<jint>(consumer_type));
}
int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!device_sensors_.is_null());
return Java_DeviceSensors_getNumberActiveDeviceMotionSensors(
AttachCurrentThread(), device_sensors_);
@@ -230,6 +235,7 @@ int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
SensorManagerAndroid::OrientationSensorType
SensorManagerAndroid::GetOrientationSensorTypeUsed() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!device_sensors_.is_null());
return static_cast<SensorManagerAndroid::OrientationSensorType>(
Java_DeviceSensors_getOrientationSensorTypeUsed(AttachCurrentThread(),
@@ -242,20 +248,7 @@ SensorManagerAndroid::GetOrientationSensorTypeUsed() {
void SensorManagerAndroid::StartFetchingDeviceLightData(
DeviceLightHardwareBuffer* buffer) {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StartFetchingLightDataOnUI(buffer);
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StartFetchingLightDataOnUI,
- base::Unretained(this),
- buffer));
- }
-}
-
-void SensorManagerAndroid::StartFetchingLightDataOnUI(
- DeviceLightHardwareBuffer* buffer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(buffer);
if (is_shutdown_)
return;
@@ -273,19 +266,7 @@ void SensorManagerAndroid::StartFetchingLightDataOnUI(
}
void SensorManagerAndroid::StopFetchingDeviceLightData() {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StopFetchingLightDataOnUI();
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StopFetchingLightDataOnUI,
- base::Unretained(this)));
-}
-
-void SensorManagerAndroid::StopFetchingLightDataOnUI() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (is_shutdown_)
return;
@@ -309,20 +290,7 @@ void SensorManagerAndroid::SetLightBufferValue(double lux) {
void SensorManagerAndroid::StartFetchingDeviceMotionData(
DeviceMotionHardwareBuffer* buffer) {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StartFetchingMotionDataOnUI(buffer);
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StartFetchingMotionDataOnUI,
- base::Unretained(this),
- buffer));
- }
-}
-
-void SensorManagerAndroid::StartFetchingMotionDataOnUI(
- DeviceMotionHardwareBuffer* buffer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(buffer);
if (is_shutdown_)
return;
@@ -345,19 +313,7 @@ void SensorManagerAndroid::StartFetchingMotionDataOnUI(
}
void SensorManagerAndroid::StopFetchingDeviceMotionData() {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StopFetchingMotionDataOnUI();
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StopFetchingMotionDataOnUI,
- base::Unretained(this)));
-}
-
-void SensorManagerAndroid::StopFetchingMotionDataOnUI() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (is_shutdown_)
return;
@@ -410,20 +366,7 @@ void SensorManagerAndroid::ClearInternalMotionBuffers() {
void SensorManagerAndroid::StartFetchingDeviceOrientationData(
DeviceOrientationHardwareBuffer* buffer) {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StartFetchingOrientationDataOnUI(buffer);
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StartFetchingOrientationDataOnUI,
- base::Unretained(this),
- buffer));
- }
-}
-
-void SensorManagerAndroid::StartFetchingOrientationDataOnUI(
- DeviceOrientationHardwareBuffer* buffer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(buffer);
if (is_shutdown_)
return;
@@ -448,19 +391,7 @@ void SensorManagerAndroid::StartFetchingOrientationDataOnUI(
}
void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StopFetchingOrientationDataOnUI();
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StopFetchingOrientationDataOnUI,
- base::Unretained(this)));
-}
-
-void SensorManagerAndroid::StopFetchingOrientationDataOnUI() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (is_shutdown_)
return;
@@ -477,33 +408,7 @@ void SensorManagerAndroid::StopFetchingOrientationDataOnUI() {
void SensorManagerAndroid::StartFetchingDeviceOrientationAbsoluteData(
DeviceOrientationHardwareBuffer* buffer) {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StartFetchingOrientationAbsoluteDataOnUI(buffer);
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &SensorManagerAndroid::StartFetchingOrientationAbsoluteDataOnUI,
- base::Unretained(this),
- buffer));
- }
-}
-
-void SensorManagerAndroid::StopFetchingDeviceOrientationAbsoluteData() {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- StopFetchingOrientationAbsoluteDataOnUI();
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SensorManagerAndroid::StopFetchingOrientationAbsoluteDataOnUI,
- base::Unretained(this)));
-}
-
-void SensorManagerAndroid::StartFetchingOrientationAbsoluteDataOnUI(
- DeviceOrientationHardwareBuffer* buffer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(buffer);
if (is_shutdown_)
return;
@@ -524,8 +429,8 @@ void SensorManagerAndroid::StartFetchingOrientationAbsoluteDataOnUI(
}
}
-void SensorManagerAndroid::StopFetchingOrientationAbsoluteDataOnUI() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void SensorManagerAndroid::StopFetchingDeviceOrientationAbsoluteData() {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (is_shutdown_)
return;
@@ -542,7 +447,7 @@ void SensorManagerAndroid::StopFetchingOrientationAbsoluteDataOnUI() {
}
void SensorManagerAndroid::Shutdown() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(thread_checker_.CalledOnValidThread());
is_shutdown_ = true;
}
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android.h b/chromium/content/browser/device_sensors/sensor_manager_android.h
index 67d28b9b591..058b6eb1117 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android.h
+++ b/chromium/content/browser/device_sensors/sensor_manager_android.h
@@ -10,11 +10,12 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
#include "content/browser/device_sensors/device_sensors_consts.h"
#include "content/common/content_export.h"
-#include "content/common/device_sensors/device_light_hardware_buffer.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
namespace base {
template <typename T>
@@ -33,7 +34,7 @@ class CONTENT_EXPORT SensorManagerAndroid {
// Must be called at startup, before GetInstance().
static bool Register(JNIEnv* env);
- // Needs to be thread-safe, because accessed from different threads.
+ // Should be called only on the UI thread.
static SensorManagerAndroid* GetInstance();
// Called from Java via JNI.
@@ -110,20 +111,6 @@ class CONTENT_EXPORT SensorManagerAndroid {
// ConsumerType.DEVICE_MOTION.
virtual int GetNumberActiveDeviceMotionSensors();
- void StartFetchingLightDataOnUI(DeviceLightHardwareBuffer* buffer);
- void StopFetchingLightDataOnUI();
-
- void StartFetchingMotionDataOnUI(DeviceMotionHardwareBuffer* buffer);
- void StopFetchingMotionDataOnUI();
-
- void StartFetchingOrientationDataOnUI(
- DeviceOrientationHardwareBuffer* buffer);
- void StopFetchingOrientationDataOnUI();
-
- void StartFetchingOrientationAbsoluteDataOnUI(
- DeviceOrientationHardwareBuffer* buffer);
- void StopFetchingOrientationAbsoluteDataOnUI();
-
private:
friend struct base::DefaultSingletonTraits<SensorManagerAndroid>;
@@ -161,6 +148,7 @@ class CONTENT_EXPORT SensorManagerAndroid {
base::Lock orientation_absolute_buffer_lock_;
bool is_shutdown_;
+ base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(SensorManagerAndroid);
};
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc b/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
index f773fd8023e..98137aae84d 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
@@ -8,8 +8,8 @@
#include "base/android/jni_android.h"
#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "content/browser/device_sensors/device_sensors_consts.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -66,7 +66,7 @@ class AndroidSensorManagerTest : public testing::Test {
std::unique_ptr<DeviceMotionHardwareBuffer> motion_buffer_;
std::unique_ptr<DeviceOrientationHardwareBuffer> orientation_buffer_;
std::unique_ptr<DeviceOrientationHardwareBuffer> orientation_absolute_buffer_;
- content::TestBrowserThreadBundle thread_bundle_;
+ base::MessageLoop message_loop_;
};
TEST_F(AndroidSensorManagerTest, ThreeDeviceMotionSensorsActive) {
diff --git a/chromium/content/browser/device_sensors/sensor_manager_chromeos.h b/chromium/content/browser/device_sensors/sensor_manager_chromeos.h
index 74c4acecbc7..7af9231b69e 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_chromeos.h
+++ b/chromium/content/browser/device_sensors/sensor_manager_chromeos.h
@@ -10,8 +10,8 @@
#include "chromeos/accelerometer/accelerometer_reader.h"
#include "chromeos/accelerometer/accelerometer_types.h"
#include "content/common/content_export.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
namespace content {
diff --git a/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc b/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
index deb3e9d137c..7a15eb81ce4 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
@@ -8,8 +8,8 @@
#include "base/macros.h"
#include "chromeos/accelerometer/accelerometer_types.h"
-#include "content/common/device_sensors/device_motion_hardware_buffer.h"
-#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn
index 2d457083e7f..d0530555ae5 100644
--- a/chromium/content/browser/devtools/BUILD.gn
+++ b/chromium/content/browser/devtools/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//tools/grit/grit_rule.gni")
+import("//third_party/inspector_protocol/inspector_protocol.gni")
group("resources") {
public_deps = [
@@ -33,6 +34,37 @@ grit("devtools_resources") {
]
}
+inspector_protocol_generate("protocol_sources") {
+ visibility = [ "//content/browser" ]
+ deps = [
+ "//third_party/WebKit/Source/core/inspector:protocol_version",
+ ]
+ _blink_protocol_path =
+ rebase_path("$root_gen_dir/blink/core/inspector/protocol.json",
+ root_build_dir)
+
+ inspector_protocol_dir = "//third_party/inspector_protocol"
+ out_dir = target_gen_dir
+ config_file = "protocol_config.json"
+ config_values = [ "protocol.path=$_blink_protocol_path" ]
+
+ inputs = [
+ "$root_gen_dir/blink/core/inspector/protocol.json",
+ config_file,
+ ]
+
+ # These are relative to $target_gen_dir.
+ outputs = [
+ "protocol/io.cc",
+ "protocol/io.h",
+ "protocol/forward.h",
+ "protocol/protocol.cc",
+ "protocol/protocol.h",
+ "protocol/tracing.cc",
+ "protocol/tracing.h",
+ ]
+}
+
action("gen_devtools_protocol_handler") {
visibility = [ "//content/browser" ]
deps = [
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index 8fd6a52f944..d4a50cefbdf 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/guid.h"
#include "content/browser/devtools/devtools_protocol_handler.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/io_handler.h"
#include "content/browser/devtools/protocol/memory_handler.h"
#include "content/browser/devtools/protocol/system_info_handler.h"
@@ -43,6 +44,7 @@ BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
dispatcher->SetSystemInfoHandler(system_info_handler_.get());
dispatcher->SetTetheringHandler(tethering_handler_.get());
dispatcher->SetTracingHandler(tracing_handler_.get());
+ NotifyCreated();
}
BrowserDevToolsAgentHost::~BrowserDevToolsAgentHost() {
@@ -79,7 +81,8 @@ void BrowserDevToolsAgentHost::Reload() {
bool BrowserDevToolsAgentHost::DispatchProtocolMessage(
const std::string& message) {
- protocol_handler_->HandleMessage(session_id(), message);
+ protocol_handler_->HandleMessage(session() ? session()->session_id() : 0,
+ message);
return true;
}
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 96a24eaccbd..b39d10c19d3 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -7,9 +7,13 @@
#include <map>
#include <vector>
+#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
+#include "base/message_loop/message_loop.h"
+#include "base/observer_list.h"
#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/forwarding_agent_host.h"
#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -17,7 +21,9 @@
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
+#include "content/browser/loader/netlog_observer.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
namespace content {
@@ -25,12 +31,8 @@ namespace {
typedef std::map<std::string, DevToolsAgentHostImpl*> Instances;
base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
-using AgentStateCallbacks =
- std::vector<const DevToolsAgentHost::AgentStateCallback*>;
-base::LazyInstance<AgentStateCallbacks>::Leaky g_callbacks =
- LAZY_INSTANCE_INITIALIZER;
-using DiscoveryCallbacks =
- std::vector<DevToolsAgentHost::DiscoveryCallback>;
+base::LazyInstance<base::ObserverList<DevToolsAgentHostObserver>>::Leaky
+ g_observers = LAZY_INSTANCE_INITIALIZER;
} // namespace
char DevToolsAgentHost::kTypePage[] = "page";
@@ -40,6 +42,8 @@ char DevToolsAgentHost::kTypeServiceWorker[] = "service_worker";
char DevToolsAgentHost::kTypeExternal[] = "external";
char DevToolsAgentHost::kTypeBrowser[] = "browser";
char DevToolsAgentHost::kTypeOther[] = "other";
+int DevToolsAgentHostImpl::s_attached_count_ = 0;
+int DevToolsAgentHostImpl::s_force_creation_count_ = 0;
// static
std::string DevToolsAgentHost::GetProtocolVersion() {
@@ -65,6 +69,14 @@ DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() {
result.push_back(host);
RenderFrameDevToolsAgentHost::AddAllAgentHosts(&result);
+
+#if DCHECK_IS_ON()
+ for (auto it : result) {
+ DevToolsAgentHostImpl* host = static_cast<DevToolsAgentHostImpl*>(it.get());
+ DCHECK(g_instances.Get().find(host->id_) != g_instances.Get().end());
+ }
+#endif
+
return result;
}
@@ -92,16 +104,14 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker(
DevToolsAgentHostImpl::DevToolsAgentHostImpl(const std::string& id)
: id_(id),
- session_id_(0),
+ last_session_id_(0),
client_(NULL) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(g_instances.Get().find(id_) == g_instances.Get().end());
- g_instances.Get()[id_] = this;
}
DevToolsAgentHostImpl::~DevToolsAgentHostImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- g_instances.Get().erase(g_instances.Get().find(id_));
+ NotifyDestroyed();
}
// static
@@ -131,13 +141,14 @@ bool DevToolsAgentHostImpl::InnerAttach(DevToolsAgentHostClient* client,
return false;
scoped_refptr<DevToolsAgentHostImpl> protect(this);
- ++session_id_;
if (client_) {
client_->AgentHostClosed(this, true);
InnerDetach();
}
client_ = client;
+ session_.reset(new DevToolsSession(this, ++last_session_id_));
Attach();
+ NotifyAttached();
return true;
}
@@ -170,6 +181,8 @@ bool DevToolsAgentHostImpl::DispatchProtocolMessage(
void DevToolsAgentHostImpl::InnerDetach() {
Detach();
io_context_.DiscardAllStreams();
+ session_.reset();
+ NotifyDetached();
}
bool DevToolsAgentHostImpl::IsAttached() {
@@ -239,7 +252,7 @@ void DevToolsAgentHostImpl::SendProtocolResponse(int session_id,
void DevToolsAgentHostImpl::SendProtocolNotification(
const std::string& message) {
- SendMessageToClient(session_id_, message);
+ SendMessageToClient(session_ ? session_->session_id() : 0, message);
}
void DevToolsAgentHostImpl::HostClosed() {
@@ -251,6 +264,7 @@ void DevToolsAgentHostImpl::HostClosed() {
DevToolsAgentHostClient* client = client_;
client_ = NULL;
client->AgentHostClosed(this, false);
+ NotifyDetached();
}
void DevToolsAgentHostImpl::InspectElement(int x, int y) {
@@ -261,7 +275,7 @@ void DevToolsAgentHostImpl::SendMessageToClient(int session_id,
if (!client_)
return;
// Filter any messages from previous sessions.
- if (session_id != session_id_)
+ if (!session_ || session_id != session_->session_id())
return;
client_->DispatchProtocolMessage(this, message);
}
@@ -288,34 +302,71 @@ void DevToolsAgentHost::DetachAllClients() {
}
// static
-void DevToolsAgentHost::AddAgentStateCallback(
- const AgentStateCallback& callback) {
- g_callbacks.Get().push_back(&callback);
+void DevToolsAgentHost::AddObserver(DevToolsAgentHostObserver* observer) {
+ if (observer->ShouldForceDevToolsAgentHostCreation()) {
+ if (!DevToolsAgentHostImpl::s_force_creation_count_) {
+ // Force all agent hosts when first observer is added.
+ DevToolsAgentHost::GetOrCreateAll();
+ }
+ DevToolsAgentHostImpl::s_force_creation_count_++;
+ }
+
+ g_observers.Get().AddObserver(observer);
+ for (const auto& id_host : g_instances.Get())
+ observer->DevToolsAgentHostCreated(id_host.second);
}
// static
-void DevToolsAgentHost::RemoveAgentStateCallback(
- const AgentStateCallback& callback) {
- if (g_callbacks == NULL)
- return;
-
- AgentStateCallbacks* callbacks_ = g_callbacks.Pointer();
- AgentStateCallbacks::iterator it =
- std::find(callbacks_->begin(), callbacks_->end(), &callback);
- DCHECK(it != callbacks_->end());
- callbacks_->erase(it);
+void DevToolsAgentHost::RemoveObserver(DevToolsAgentHostObserver* observer) {
+ if (observer->ShouldForceDevToolsAgentHostCreation())
+ DevToolsAgentHostImpl::s_force_creation_count_--;
+ g_observers.Get().RemoveObserver(observer);
}
// static
-void DevToolsAgentHostImpl::NotifyCallbacks(
- DevToolsAgentHostImpl* agent_host, bool attached) {
- AgentStateCallbacks copy(g_callbacks.Get());
- DevToolsManager* manager = DevToolsManager::GetInstance();
- manager->AgentHostStateChanged(agent_host, attached);
- if (manager->delegate())
- manager->delegate()->DevToolsAgentStateChanged(agent_host, attached);
- for (AgentStateCallbacks::iterator it = copy.begin(); it != copy.end(); ++it)
- (*it)->Run(agent_host, attached);
+bool DevToolsAgentHostImpl::ShouldForceCreation() {
+ return !!s_force_creation_count_;
+}
+
+void DevToolsAgentHostImpl::NotifyCreated() {
+ DCHECK(g_instances.Get().find(id_) == g_instances.Get().end());
+ g_instances.Get()[id_] = this;
+ for (auto& observer : g_observers.Get())
+ observer.DevToolsAgentHostCreated(this);
+}
+
+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);
+}
+
+void DevToolsAgentHostImpl::NotifyDestroyed() {
+ DCHECK(g_instances.Get().find(id_) != g_instances.Get().end());
+ for (auto& observer : g_observers.Get())
+ observer.DevToolsAgentHostDestroyed(this);
+ g_instances.Get().erase(id_);
}
// DevToolsMessageChunkProcessor -----------------------------------------------
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index 435f34e5e74..794bb7f47d8 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -23,6 +23,7 @@ class Message;
namespace content {
class BrowserContext;
+class DevToolsSession;
// Describes interface for managing devtools agents from the browser process.
class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
@@ -54,6 +55,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
void ConnectWebContents(WebContents* wc) override;
bool Inspect();
+ void SendMessageToClient(int session_id, const std::string& message);
// DevToolsProtocolDelegate implementation.
void SendProtocolResponse(int session_id,
@@ -64,26 +66,33 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
DevToolsAgentHostImpl(const std::string& id);
~DevToolsAgentHostImpl() override;
+ static bool ShouldForceCreation();
+
virtual bool DispatchProtocolMessage(const std::string& message) = 0;
virtual void InspectElement(int x, int y);
+ void NotifyCreated();
void HostClosed();
- void SendMessageToClient(int session_id, const std::string& message);
devtools::DevToolsIOContext* GetIOContext() { return &io_context_; }
- int session_id() { DCHECK(client_); return session_id_; }
-
- static void NotifyCallbacks(DevToolsAgentHostImpl* agent_host, bool attached);
+ DevToolsSession* session() { return session_.get(); }
private:
friend class DevToolsAgentHost; // for static methods
bool InnerAttach(DevToolsAgentHostClient* client, bool force);
void InnerDetach();
+ void NotifyAttached();
+ void NotifyDetached();
+ void NotifyDestroyed();
const std::string id_;
int session_id_;
+ int last_session_id_;
+ std::unique_ptr<DevToolsSession> session_;
DevToolsAgentHostClient* client_;
devtools::DevToolsIOContext io_context_;
+ static int s_attached_count_;
+ static int s_force_creation_count_;
};
class DevToolsMessageChunkProcessor {
diff --git a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
index 37613b36483..9c101d26b87 100644
--- a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -17,7 +17,10 @@
namespace content {
namespace {
-const char kCompatibilityScript[] = "devtools.js";
+const char kCompatibilityScript[] = "devtools_compatibility.js";
+const char kCompatibilityScriptSourceURL[] =
+ "\n//# "
+ "sourceURL=chrome-devtools://devtools/bundled/devtools_compatibility.js";
}
// static
@@ -48,8 +51,9 @@ DevToolsFrontendHostImpl::DevToolsFrontendHostImpl(
handle_message_callback_(handle_message_callback) {
frontend_main_frame->Send(new DevToolsMsg_SetupDevToolsClient(
frontend_main_frame->GetRoutingID(),
- DevToolsFrontendHost::GetFrontendResource(
- kCompatibilityScript).as_string()));
+ DevToolsFrontendHost::GetFrontendResource(kCompatibilityScript)
+ .as_string() +
+ kCompatibilityScriptSourceURL));
}
DevToolsFrontendHostImpl::~DevToolsFrontendHostImpl() {
diff --git a/chromium/content/browser/devtools/devtools_http_handler.h b/chromium/content/browser/devtools/devtools_http_handler.h
index 207b2a90e12..657abb4f1a7 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.h
+++ b/chromium/content/browser/devtools/devtools_http_handler.h
@@ -15,8 +15,6 @@
#include "content/public/browser/devtools_agent_host.h"
#include "net/http/http_status_code.h"
-class GURL;
-
namespace base {
class DictionaryValue;
class Thread;
@@ -31,13 +29,11 @@ class DevToolsSocketFactory;
namespace net {
class IPEndPoint;
class HttpServerRequestInfo;
-class ServerSocket;
}
namespace content {
class DevToolsAgentHostClientImpl;
-class DevToolsHttpHandlerDelegate;
class ServerWrapper;
// This class is used for managing DevTools remote debugging server.
diff --git a/chromium/content/browser/devtools/devtools_manager.cc b/chromium/content/browser/devtools/devtools_manager.cc
index 70059c6f251..efd7bd71af2 100644
--- a/chromium/content/browser/devtools/devtools_manager.cc
+++ b/chromium/content/browser/devtools/devtools_manager.cc
@@ -45,34 +45,10 @@ DevToolsManager* DevToolsManager::GetInstance() {
}
DevToolsManager::DevToolsManager()
- : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()),
- attached_hosts_count_(0) {
+ : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()) {
}
DevToolsManager::~DevToolsManager() {
- DCHECK(!attached_hosts_count_);
-}
-
-void DevToolsManager::AgentHostStateChanged(
- DevToolsAgentHostImpl* agent_host, bool attached) {
- if (attached) {
- if (!attached_hosts_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&NetLogObserver::Attach,
- GetContentClient()->browser()->GetNetLog()));
- }
- ++attached_hosts_count_;
- } else {
- --attached_hosts_count_;
- if (!attached_hosts_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&NetLogObserver::Detach));
- }
- }
}
void DevToolsManager::SetHttpHandler(
diff --git a/chromium/content/browser/devtools/devtools_manager.h b/chromium/content/browser/devtools/devtools_manager.h
index 2ae7049ed41..90f075d36ea 100644
--- a/chromium/content/browser/devtools/devtools_manager.h
+++ b/chromium/content/browser/devtools/devtools_manager.h
@@ -15,7 +15,6 @@
namespace content {
-class DevToolsAgentHostImpl;
class DevToolsHttpHandler;
// This class is a singleton that manage global DevTools state for the whole
@@ -32,8 +31,6 @@ class CONTENT_EXPORT DevToolsManager {
DevToolsManagerDelegate* delegate() const { return delegate_.get(); }
- void AgentHostStateChanged(DevToolsAgentHostImpl* agent_host, bool attached);
-
void SetHttpHandler(std::unique_ptr<DevToolsHttpHandler> http_handler);
private:
@@ -41,7 +38,6 @@ class CONTENT_EXPORT DevToolsManager {
std::unique_ptr<DevToolsManagerDelegate> delegate_;
std::unique_ptr<DevToolsHttpHandler> http_handler_;
- int attached_hosts_count_;
DISALLOW_COPY_AND_ASSIGN(DevToolsManager);
};
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index ee35e6b3aac..4f97266d99e 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -89,7 +89,9 @@ class TestWebContentsDelegate : public WebContentsDelegate {
TestWebContentsDelegate() : renderer_unresponsive_received_(false) {}
// Notification that the contents is hung.
- void RendererUnresponsive(WebContents* source) override {
+ void RendererUnresponsive(
+ WebContents* source,
+ const WebContentsUnresponsiveState& unresponsive_state) override {
renderer_unresponsive_received_ = true;
}
@@ -146,8 +148,8 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
// Start with a short timeout.
inspected_rvh->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(10), blink::WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -159,8 +161,8 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
client_host.Close();
// Start with a short timeout.
inspected_rvh->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(10), blink::WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -178,7 +180,7 @@ TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int pending_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetMainFrame(), 1, pending_id, true,
+ contents()->TestDidNavigate(contents()->GetMainFrame(), pending_id, true,
url, ui::PAGE_TRANSITION_TYPED);
contents()->GetMainFrame()->SimulateNavigationStop();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -201,7 +203,7 @@ TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
pending_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetMainFrame(), 1, pending_id, false,
+ contents()->TestDidNavigate(contents()->GetMainFrame(), pending_id, false,
url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(client_host.agent_host(),
diff --git a/chromium/content/browser/devtools/devtools_protocol_handler.h b/chromium/content/browser/devtools/devtools_protocol_handler.h
index b91c2eb8aa1..180101413a0 100644
--- a/chromium/content/browser/devtools/devtools_protocol_handler.h
+++ b/chromium/content/browser/devtools/devtools_protocol_handler.h
@@ -11,7 +11,6 @@ namespace content {
class DevToolsAgentHost;
class DevToolsAgentHostImpl;
-class DevToolsProtocolDelegate;
class DevToolsProtocolHandler {
public:
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
new file mode 100644
index 00000000000..cf37d6cb0f3
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -0,0 +1,35 @@
+// 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/devtools_session.h"
+
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/protocol/protocol.h"
+
+namespace content {
+
+DevToolsSession::DevToolsSession(
+ DevToolsAgentHostImpl* agent_host,
+ int session_id)
+ : agent_host_(agent_host),
+ session_id_(session_id),
+ dispatcher_(new protocol::UberDispatcher(this)) {
+}
+
+DevToolsSession::~DevToolsSession() {}
+
+void DevToolsSession::sendProtocolResponse(
+ int call_id,
+ const std::string& message) {
+ agent_host_->SendMessageToClient(session_id_, message);
+}
+
+void DevToolsSession::sendProtocolNotification(const std::string& message) {
+ agent_host_->SendMessageToClient(session_id_, message);
+}
+
+void DevToolsSession::flushProtocolNotifications() {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
new file mode 100644
index 00000000000..829e58965bf
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -0,0 +1,30 @@
+// 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/protocol/forward.h"
+
+namespace content {
+
+class DevToolsAgentHostImpl;
+
+class DevToolsSession : public protocol::FrontendChannel {
+ public:
+ DevToolsSession(DevToolsAgentHostImpl* agent_host, int session_id);
+ ~DevToolsSession() override;
+
+ int session_id() { return session_id_; }
+ protocol::UberDispatcher* dispatcher() { return dispatcher_.get(); }
+
+ private:
+ // protocol::FrontendChannel implementation.
+ void sendProtocolResponse(int call_id, const std::string& message) override;
+ void sendProtocolNotification(const std::string& message) override;
+ void flushProtocolNotifications() override;
+
+ DevToolsAgentHostImpl* agent_host_;
+ int session_id_;
+ std::unique_ptr<protocol::UberDispatcher> dispatcher_;
+};
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.cc b/chromium/content/browser/devtools/forwarding_agent_host.cc
index cc07e72a017..98b89545dc9 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.cc
+++ b/chromium/content/browser/devtools/forwarding_agent_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/devtools/forwarding_agent_host.h"
#include "base/bind.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/inspector_handler.h"
namespace content {
@@ -14,13 +15,14 @@ ForwardingAgentHost::ForwardingAgentHost(
std::unique_ptr<DevToolsExternalAgentProxyDelegate> delegate)
: DevToolsAgentHostImpl(id),
delegate_(std::move(delegate)) {
+ NotifyCreated();
}
ForwardingAgentHost::~ForwardingAgentHost() {
}
void ForwardingAgentHost::DispatchOnClientHost(const std::string& message) {
- SendMessageToClient(session_id(), message);
+ SendMessageToClient(session() ? session()->session_id() : 0, message);
}
void ForwardingAgentHost::ConnectionClosed() {
diff --git a/chromium/content/browser/devtools/page_navigation_throttle.cc b/chromium/content/browser/devtools/page_navigation_throttle.cc
index cbc6018b964..3b1e9e5f3ad 100644
--- a/chromium/content/browser/devtools/page_navigation_throttle.cc
+++ b/chromium/content/browser/devtools/page_navigation_throttle.cc
@@ -57,16 +57,22 @@ void PageNavigationThrottle::AlwaysProceed() {
void PageNavigationThrottle::Resume() {
if (!navigation_deferred_)
return;
- navigation_handle()->Resume();
navigation_deferred_ = false;
+ navigation_handle()->Resume();
+
+ // Do not add code after this as the PageNavigationThrottle may be deleted by
+ // the line above.
}
void PageNavigationThrottle::CancelDeferredNavigation(
NavigationThrottle::ThrottleCheckResult result) {
if (!navigation_deferred_)
return;
- navigation_handle()->CancelDeferredNavigation(result);
navigation_deferred_ = false;
+ navigation_handle()->CancelDeferredNavigation(result);
+
+ // Do not add code after this as the PageNavigationThrottle may be deleted by
+ // the line above.
}
} // namespace devtools
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
deleted file mode 100644
index aabbf40c431..00000000000
--- a/chromium/content/browser/devtools/protocol/browser_handler.cc
+++ /dev/null
@@ -1,170 +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/protocol/browser_handler.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "content/browser/devtools/devtools_manager.h"
-#include "content/public/browser/devtools_manager_delegate.h"
-
-namespace content {
-namespace devtools {
-namespace browser {
-
-using Response = DevToolsProtocolClient::Response;
-
-BrowserHandler::BrowserHandler()
- : weak_factory_(this) {
-}
-
-BrowserHandler::~BrowserHandler() {
-}
-
-void BrowserHandler::SetClient(std::unique_ptr<Client> client) {
- client_.swap(client);
-}
-
-void BrowserHandler::Detached() {
- for (const auto& host : attached_hosts_)
- host->DetachClient(this);
- attached_hosts_.clear();
-}
-
-Response BrowserHandler::CreateBrowserContext(std::string* out_context_id) {
- // For layering reasons this needs to be handled by
- // DevToolsManagerDelegate::HandleCommand.
- return Response::ServerError("Not supported");
-}
-
-Response BrowserHandler::DisposeBrowserContext(const std::string& context_id,
- bool* out_success) {
- // For layering reasons this needs to be handled by
- // DevToolsManagerDelegate::HandleCommand.
- return Response::ServerError("Not supported");
-}
-
-Response BrowserHandler::CreateTarget(const std::string& url,
- const int* width,
- const int* height,
- const std::string* context_id,
- std::string* out_target_id) {
- DevToolsManagerDelegate* delegate =
- DevToolsManager::GetInstance()->delegate();
- if (!delegate)
- return Response::ServerError("Not supported");
- scoped_refptr<content::DevToolsAgentHost> agent_host =
- delegate->CreateNewTarget(GURL(url));
- if (!agent_host)
- return Response::ServerError("Not supported");
- *out_target_id = agent_host->GetId();
- return Response::OK();
-}
-
-Response BrowserHandler::CloseTarget(const std::string& target_id,
- bool* out_success) {
- scoped_refptr<DevToolsAgentHost> agent_host =
- DevToolsAgentHost::GetForId(target_id);
- if (!agent_host)
- return Response::ServerError("No target with given id found");
- *out_success = agent_host->Close();
- return Response::OK();
-}
-
-Response BrowserHandler::GetTargets(DevToolsCommandId command_id) {
- DevToolsAgentHost::DiscoverAllHosts(
- base::Bind(&BrowserHandler::RespondToGetTargets,
- weak_factory_.GetWeakPtr(),
- command_id));
- return Response::OK();
-}
-
-void BrowserHandler::RespondToGetTargets(
- DevToolsCommandId command_id,
- DevToolsAgentHost::List agents) {
- std::vector<scoped_refptr<devtools::browser::TargetInfo>> infos;
- for (const auto& agent_host : agents) {
- scoped_refptr<devtools::browser::TargetInfo> info =
- devtools::browser::TargetInfo::Create()->
- set_target_id(agent_host->GetId())->
- set_type(agent_host->GetType())->
- set_title(agent_host->GetTitle())->
- set_url(agent_host->GetURL().spec());
- infos.push_back(info);
- }
- client_->SendGetTargetsResponse(
- command_id,
- GetTargetsResponse::Create()->set_target_info(std::move(infos)));
-}
-
-Response BrowserHandler::Attach(DevToolsCommandId command_id,
- const std::string& target_id) {
- // Discover in order to get ahold of the items.
- DevToolsAgentHost::DiscoverAllHosts(
- base::Bind(&BrowserHandler::RespondToAttach,
- weak_factory_.GetWeakPtr(), command_id, target_id));
- return Response::OK();
-}
-
-void BrowserHandler::RespondToAttach(DevToolsCommandId command_id,
- const std::string& target_id,
- DevToolsAgentHost::List agents) {
- // We were discovering to get ahold of the items, discard them.
- scoped_refptr<DevToolsAgentHost> agent_host =
- DevToolsAgentHost::GetForId(target_id);
- bool success = false;
- if (agent_host)
- success = agent_host->AttachClient(this);
- attached_hosts_.push_back(agent_host);
- client_->SendAttachResponse(
- command_id,
- AttachResponse::Create()->set_success(success));
-}
-
-Response BrowserHandler::Detach(const std::string& target_id,
- bool* out_success) {
- scoped_refptr<DevToolsAgentHost> agent_host =
- DevToolsAgentHost::GetForId(target_id);
- auto it = std::find(
- attached_hosts_.begin(), attached_hosts_.end(), agent_host);
- if (it != attached_hosts_.end())
- attached_hosts_.erase(it);
- *out_success = agent_host && agent_host->DetachClient(this);
- return Response::OK();
-}
-
-Response BrowserHandler::SendMessage(const std::string& target_id,
- const std::string& message) {
- scoped_refptr<DevToolsAgentHost> agent_host =
- DevToolsAgentHost::GetForId(target_id);
- if (!agent_host)
- return Response::ServerError("No target with given id found");
- agent_host->DispatchProtocolMessage(this, message);
- return Response::OK();
-}
-
-Response BrowserHandler::SetRemoteLocations(
- const std::vector<std::unique_ptr<base::DictionaryValue>>& locations) {
- return Response::OK();
-}
-
-void BrowserHandler::DispatchProtocolMessage(
- DevToolsAgentHost* agent_host, const std::string& message) {
- client_->DispatchMessage(DispatchMessageParams::Create()->
- set_target_id(agent_host->GetId())->
- set_message(message));
-}
-
-void BrowserHandler::AgentHostClosed(DevToolsAgentHost* agent_host,
- bool replaced_with_another_client) {
- auto it = std::find(
- attached_hosts_.begin(), attached_hosts_.end(), agent_host);
- if (it != attached_hosts_.end())
- attached_hosts_.erase(it);
-}
-
-} // namespace browser
-} // namespace devtools
-} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.h b/chromium/content/browser/devtools/protocol/browser_handler.h
deleted file mode 100644
index 171e962da4f..00000000000
--- a/chromium/content/browser/devtools/protocol/browser_handler.h
+++ /dev/null
@@ -1,78 +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_PROTOCOL_BROWSER_HANDLER_H_
-#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
-
-#include <stdint.h>
-
-#include "base/memory/weak_ptr.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
-#include "content/public/browser/devtools_agent_host.h"
-
-namespace net {
-class ServerSocket;
-}
-
-// Windows headers will redefine SendMessage.
-#ifdef SendMessage
-#undef SendMessage
-#endif
-
-namespace content {
-namespace devtools {
-namespace browser {
-
-class BrowserHandler : public DevToolsAgentHostClient {
- public:
- using Response = DevToolsProtocolClient::Response;
-
- BrowserHandler();
- ~BrowserHandler() override;
-
- void SetClient(std::unique_ptr<Client> client);
- void Detached();
-
- Response CreateBrowserContext(std::string* out_context_id);
- Response DisposeBrowserContext(const std::string& context_id,
- bool* out_success);
- Response CreateTarget(const std::string& url,
- const int* width,
- const int* height,
- const std::string* context_id,
- std::string* out_target_id);
- Response CloseTarget(const std::string& target_id, bool* out_success);
- Response GetTargets(DevToolsCommandId command_id);
- Response Attach(DevToolsCommandId command_id,
- const std::string& target_id);
- Response Detach(const std::string& target_id, bool* out_success);
- Response SendMessage(const std::string& target_id,
- const std::string& message);
- Response SetRemoteLocations(
- const std::vector<std::unique_ptr<base::DictionaryValue>>&);
-
- private:
- void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
- const std::string& message) override;
-
- void AgentHostClosed(DevToolsAgentHost* agent_host,
- bool replaced_with_another_client) override;
-
- void RespondToGetTargets(DevToolsCommandId command_id,
- DevToolsAgentHost::List list);
- void RespondToAttach(DevToolsCommandId command_id,
- const std::string& target_id,
- DevToolsAgentHost::List agents);
-
- std::unique_ptr<Client> client_;
- DevToolsAgentHost::List attached_hosts_;
- base::WeakPtrFactory<BrowserHandler> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(BrowserHandler);
-};
-
-} // namespace browser
-} // namespace devtools
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/color_picker.cc b/chromium/content/browser/devtools/protocol/color_picker.cc
index 18faba861a5..a5b17772017 100644
--- a/chromium/content/browser/devtools/protocol/color_picker.cc
+++ b/chromium/content/browser/devtools/protocol/color_picker.cc
@@ -11,7 +11,7 @@
#include "content/common/cursors/webcursor.h"
#include "content/public/common/screen_info.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 616819bc2c5..025f6bde754 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -39,6 +39,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -117,9 +118,9 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
return true;
}
- void CancelActiveAndPendingDialogs(WebContents* web_contents) override {}
-
- void ResetDialogState(WebContents* web_contents) override {}
+ void CancelDialogs(WebContents* web_contents,
+ bool suppress_callbacks,
+ bool reset_state) override {}
private:
DialogClosedCallback callback_;
@@ -150,11 +151,11 @@ class DevToolsProtocolTest : public ContentBrowserTest,
protected:
// WebContentsDelegate method:
- bool AddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override {
+ bool DidAddMessageToConsole(WebContents* source,
+ int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override {
console_messages_.push_back(base::UTF16ToUTF8(message));
return true;
}
@@ -230,9 +231,34 @@ class DevToolsProtocolTest : public ContentBrowserTest,
}
}
- void WaitForNotification(const std::string& notification) {
+ std::unique_ptr<base::DictionaryValue> WaitForNotification(
+ const std::string& notification) {
+ return WaitForNotification(notification, false);
+ }
+
+ std::unique_ptr<base::DictionaryValue> WaitForNotification(
+ const std::string& notification,
+ bool allow_existing) {
+ if (allow_existing) {
+ for (size_t i = 0; i < notifications_.size(); i++) {
+ if (notifications_[i] == notification) {
+ 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;
RunMessageLoop();
+ return std::move(waiting_for_notification_params_);
+ }
+
+ void ClearNotifications() {
+ notifications_.clear();
+ notification_params_.clear();
}
struct ExpectedNavigation {
@@ -254,24 +280,21 @@ class DevToolsProtocolTest : public ContentBrowserTest,
void ProcessNavigationsAnyOrder(
std::vector<ExpectedNavigation> expected_navigations) {
while (!expected_navigations.empty()) {
- WaitForNotification("Page.navigationRequested");
- ASSERT_TRUE(requested_notification_params_.get());
+ std::unique_ptr<base::DictionaryValue> params =
+ WaitForNotification("Page.navigationRequested");
std::string url;
- ASSERT_TRUE(requested_notification_params_->GetString("url", &url));
+ ASSERT_TRUE(params->GetString("url", &url));
// The url will typically have a random port which we want to remove.
url = RemovePort(GURL(url));
int navigation_id;
- ASSERT_TRUE(requested_notification_params_->GetInteger("navigationId",
- &navigation_id));
+ ASSERT_TRUE(params->GetInteger("navigationId", &navigation_id));
bool is_in_main_frame;
- ASSERT_TRUE(requested_notification_params_->GetBoolean(
- "isInMainFrame", &is_in_main_frame));
+ ASSERT_TRUE(params->GetBoolean( "isInMainFrame", &is_in_main_frame));
bool is_redirect;
- ASSERT_TRUE(requested_notification_params_->GetBoolean("isRedirect",
- &is_redirect));
+ ASSERT_TRUE(params->GetBoolean("isRedirect", &is_redirect));
bool navigation_was_expected;
for (auto it = expected_navigations.begin();
@@ -281,11 +304,11 @@ class DevToolsProtocolTest : public ContentBrowserTest,
continue;
}
- std::unique_ptr<base::DictionaryValue> params(
+ std::unique_ptr<base::DictionaryValue> process_params(
new base::DictionaryValue());
- params->SetString("response", it->navigation_response);
- params->SetInteger("navigationId", navigation_id);
- SendCommand("Page.processNavigation", std::move(params), false);
+ process_params->SetString("response", it->navigation_response);
+ process_params->SetInteger("navigationId", navigation_id);
+ SendCommand("Page.processNavigation", std::move(process_params), false);
navigation_was_expected = true;
expected_navigations.erase(it);
@@ -322,7 +345,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
std::vector<int> result_ids_;
std::vector<std::string> notifications_;
std::vector<std::string> console_messages_;
- std::unique_ptr<base::DictionaryValue> requested_notification_params_;
+ std::vector<std::unique_ptr<base::DictionaryValue>> notification_params_;
private:
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
@@ -345,14 +368,17 @@ class DevToolsProtocolTest : public ContentBrowserTest,
std::string notification;
EXPECT_TRUE(root->GetString("method", &notification));
notifications_.push_back(notification);
+ base::DictionaryValue* params;
+ if (root->GetDictionary("params", &params)) {
+ notification_params_.push_back(params->CreateDeepCopy());
+ } else {
+ notification_params_.push_back(
+ base::WrapUnique(new base::DictionaryValue()));
+ }
if (waiting_for_notification_ == notification) {
- base::DictionaryValue* params;
- if (root->GetDictionary("params", &params)) {
- requested_notification_params_ = params->CreateDeepCopy();
- } else {
- requested_notification_params_.reset();
- }
waiting_for_notification_ = std::string();
+ waiting_for_notification_params_ = base::WrapUnique(
+ notification_params_[notification_params_.size() - 1]->DeepCopy());
base::MessageLoop::current()->QuitNow();
}
}
@@ -363,6 +389,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
}
std::string waiting_for_notification_;
+ 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_;
@@ -735,8 +762,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) {
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteNoDetach) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url1 = embedded_test_server()->GetURL(
"A.com", "/devtools/navigation.html");
@@ -768,8 +795,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReconnectPreservesState) {
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSitePauseInBeforeUnload) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURLBlockUntilNavigationsComplete(shell(),
embedded_test_server()->GetURL("A.com", "/devtools/navigation.html"), 1);
@@ -790,8 +817,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSitePauseInBeforeUnload) {
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectDuringFrameSwap) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url1 =
embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");
@@ -917,7 +944,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateAndCloseTarget) {
EXPECT_EQ(1u, shell()->windows().size());
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetString("url", "about:blank");
- SendCommand("Browser.createTarget", std::move(params), true);
+ SendCommand("Target.createTarget", std::move(params), true);
std::string target_id;
EXPECT_TRUE(result_->GetString("targetId", &target_id));
EXPECT_EQ(2u, shell()->windows().size());
@@ -927,7 +954,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateAndCloseTarget) {
bool success;
params.reset(new base::DictionaryValue());
params->SetString("targetId", target_id);
- SendCommand("Browser.closeTarget", std::move(params), true);
+ SendCommand("Target.closeTarget", std::move(params), true);
EXPECT_TRUE(result_->GetBoolean("success", &success));
EXPECT_TRUE(success);
}
@@ -935,9 +962,9 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateAndCloseTarget) {
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserGetTargets) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
- SendCommand("Browser.getTargets", nullptr, true);
+ SendCommand("Target.getTargets", nullptr, true);
base::ListValue* target_infos;
- EXPECT_TRUE(result_->GetList("targetInfo", &target_infos));
+ EXPECT_TRUE(result_->GetList("targetInfos", &target_infos));
EXPECT_EQ(1u, target_infos->GetSize());
base::DictionaryValue* target_info;
EXPECT_TRUE(target_infos->GetDictionary(0u, &target_info));
@@ -946,9 +973,9 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserGetTargets) {
EXPECT_TRUE(target_info->GetString("type", &type));
EXPECT_TRUE(target_info->GetString("title", &title));
EXPECT_TRUE(target_info->GetString("url", &url));
- EXPECT_EQ(type, "page");
- EXPECT_EQ(title, "about:blank");
- EXPECT_EQ(url, "about:blank");
+ EXPECT_EQ("page", type);
+ EXPECT_EQ("about:blank", title);
+ EXPECT_EQ("about:blank", url);
}
namespace {
@@ -1039,8 +1066,8 @@ class IsolatedDevToolsProtocolTest : public DevToolsProtocolTest {
IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
ControlNavigationsChildFrames) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
// Navigate to about:blank first so we can make sure there is a target page we
// can attach to, and have Page.setControlNavigations complete before we start
@@ -1217,4 +1244,161 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ShowCertificateViewer) {
EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate());
}
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetDiscovery) {
+ std::string temp;
+ std::set<std::string> ids;
+ std::unique_ptr<base::DictionaryValue> command_params;
+ std::unique_ptr<base::DictionaryValue> params;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL first_url = embedded_test_server()->GetURL("/devtools/navigation.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), first_url, 1);
+
+ GURL second_url = embedded_test_server()->GetURL("/devtools/navigation.html");
+ Shell* second = CreateBrowser();
+ NavigateToURLBlockUntilNavigationsComplete(second, second_url, 1);
+
+ Attach();
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetBoolean("discover", true);
+ SendCommand("Target.setDiscoverTargets", std::move(command_params), true);
+ params = WaitForNotification("Target.targetCreated", true);
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
+ EXPECT_EQ("page", temp);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) == ids.end());
+ ids.insert(temp);
+ params = WaitForNotification("Target.targetCreated", true);
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
+ EXPECT_EQ("page", temp);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) == ids.end());
+ ids.insert(temp);
+ EXPECT_TRUE(notifications_.empty());
+
+ GURL third_url = embedded_test_server()->GetURL("/devtools/navigation.html");
+ Shell* third = CreateBrowser();
+ NavigateToURLBlockUntilNavigationsComplete(third, third_url, 1);
+ params = WaitForNotification("Target.targetCreated", true);
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
+ EXPECT_EQ("page", temp);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) == ids.end());
+ std::string attached_id = temp;
+ ids.insert(temp);
+ EXPECT_TRUE(notifications_.empty());
+
+ second->Close();
+ second = nullptr;
+ params = WaitForNotification("Target.targetDestroyed", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) != ids.end());
+ ids.erase(temp);
+ EXPECT_TRUE(notifications_.empty());
+
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetString("targetId", attached_id);
+ SendCommand("Target.attachToTarget", std::move(command_params), true);
+ params = WaitForNotification("Target.attachedToTarget", true);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp));
+ EXPECT_EQ(attached_id, temp);
+ EXPECT_TRUE(notifications_.empty());
+
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetBoolean("discover", false);
+ SendCommand("Target.setDiscoverTargets", std::move(command_params), true);
+ params = WaitForNotification("Target.targetDestroyed", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) != ids.end());
+ ids.erase(temp);
+ params = WaitForNotification("Target.targetDestroyed", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_TRUE(ids.find(temp) != ids.end());
+ ids.erase(temp);
+ EXPECT_TRUE(notifications_.empty());
+
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetString("targetId", attached_id);
+ SendCommand("Target.detachFromTarget", std::move(command_params), true);
+ params = WaitForNotification("Target.detachedFromTarget", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_EQ(attached_id, temp);
+ EXPECT_TRUE(notifications_.empty());
+}
+
+class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ DevToolsProtocolTest::SetUpCommandLine(command_line);
+ IsolateAllSitesForTesting(command_line);
+ };
+
+ void SetUpOnMainThread() override {
+ DevToolsProtocolTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) {
+ std::string temp;
+ std::string target_id;
+ std::unique_ptr<base::DictionaryValue> command_params;
+ std::unique_ptr<base::DictionaryValue> params;
+
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
+ NavigateToURLBlockUntilNavigationsComplete(shell(), main_url, 1);
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ // Load cross-site page into iframe.
+ GURL::Replacements replace_host;
+ GURL cross_site_url(embedded_test_server()->GetURL("/title1.html"));
+ replace_host.SetHostStr("foo.com");
+ cross_site_url = cross_site_url.ReplaceComponents(replace_host);
+ NavigateFrameToURL(root->child_at(0), cross_site_url);
+
+ // Enable auto-attach.
+ Attach();
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetBoolean("autoAttach", true);
+ command_params->SetBoolean("waitForDebuggerOnStart", true);
+ SendCommand("Target.setAutoAttach", std::move(command_params), true);
+ EXPECT_TRUE(notifications_.empty());
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetBoolean("value", true);
+ SendCommand("Target.setAttachToFrames", std::move(command_params), false);
+ params = WaitForNotification("Target.attachedToTarget", true);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
+ EXPECT_EQ("iframe", temp);
+
+ // Load same-site page into iframe.
+ FrameTreeNode* child = root->child_at(0);
+ GURL http_url(embedded_test_server()->GetURL("/title1.html"));
+ NavigateFrameToURL(child, http_url);
+ params = WaitForNotification("Target.detachedFromTarget", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_EQ(target_id, temp);
+
+ // Navigate back to cross-site iframe.
+ NavigateFrameToURL(root->child_at(0), cross_site_url);
+ params = WaitForNotification("Target.attachedToTarget", true);
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
+ EXPECT_EQ("iframe", temp);
+
+ // Disable auto-attach.
+ command_params.reset(new base::DictionaryValue());
+ command_params->SetBoolean("autoAttach", false);
+ command_params->SetBoolean("waitForDebuggerOnStart", false);
+ SendCommand("Target.setAutoAttach", std::move(command_params), false);
+ params = WaitForNotification("Target.detachedFromTarget", true);
+ EXPECT_TRUE(params->GetString("targetId", &temp));
+ EXPECT_EQ(target_id, temp);
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
index 379e37a91f2..7b0f58c2d2f 100755
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -481,6 +481,9 @@ def DeclareStruct(json_properties, mapping):
del prop_map["declared_name"]
ResolveType(json_prop, prop_map)
prop_map["declared_name"] = mapping["declared_name"]
+ if prop_map["pass_type"].find(mapping["declared_name"]) != -1:
+ prop_map["pass_type"] = prop_map["pass_type"].replace(
+ mapping["declared_name"], mapping["declared_name"] + "Builder<0>")
if json_prop.get("optional"):
methods.append(tmpl_builder_setter_opt.substitute(prop_map))
else:
@@ -640,6 +643,39 @@ fields = []
includes = []
fields_init = []
+browser_domains_list = ["Inspector", "Memory", "Page", "Emulation", "Security",
+ "IO", "Target", "ServiceWorker", "Input", "Tracing", "Storage",
+ "SystemInfo", "Tethering", "Schema"]
+browser_commands_list = [
+ "DOM.setFileInputFiles",
+ "Network.enable",
+ "Network.disable",
+ "Network.clearBrowserCache",
+ "Network.clearBrowserCookies",
+ "Network.getCookies",
+ "Network.deleteCookie",
+ "Network.setCookie",
+ "Network.canEmulateNetworkConditions",
+ "Network.emulateNetworkConditions"]
+async_commands_list = [
+ "Page.getResourceContent",
+ "Page.searchInResource",
+ "Page.captureScreenshot",
+ "Network.getCookies",
+ "Network.deleteCookie",
+ "Network.setCookie",
+ "IO.read",
+ "Input.synthesizePinchGesture",
+ "Input.synthesizeScrollGesture",
+ "Input.synthesizeTapGesture",
+ "Tracing.start",
+ "Tracing.end",
+ "Tracing.getCategories",
+ "Tracing.requestMemoryDump",
+ "SystemInfo.getInfo",
+ "Tethering.bind",
+ "Tethering.unbind"]
+
for json_domain in all_domains:
domain_map = {}
domain_map["Domain"] = json_domain["domain"]
@@ -653,8 +689,9 @@ for json_domain in all_domains:
if "commands" in json_domain:
for json_command in json_domain["commands"]:
- if (not ("handlers" in json_command) or
- not ("browser" in json_command["handlers"])):
+ full_command_name = json_domain["domain"] + "." + json_command["name"]
+ if (json_domain["domain"] not in browser_domains_list and
+ full_command_name not in browser_commands_list):
continue
domain_empty = False
@@ -700,7 +737,7 @@ for json_domain in all_domains:
args.append(
tmpl_arg_req.substitute(param_map, param_pass=param_pass))
- if json_command.get("async"):
+ if full_command_name in async_commands_list:
domain_needs_client = True
json_returns = []
if "returns" in json_command:
@@ -724,9 +761,13 @@ for json_domain in all_domains:
param_map = command_map.copy()
param_map["proto_param"] = json_param["name"]
param_map["param"] = Uncamelcase(json_param["name"])
- if json_param.get("optional"):
+ is_string = "type" in json_param and json_param["type"] == "string"
+ if json_param.get("optional") and not is_string:
# TODO(vkuzkokov) Implement Optional<T> for value types.
- raise Exception("Optional return values are not implemented")
+ raise Exception(
+ "Optional return values are not implemented (%s.%s.%s)" %
+ (param_map["Domain"], param_map["command"],
+ param_map["proto_param"]))
ResolveType(json_param, param_map)
prep.append(tmpl_prep_output.substitute(param_map))
args.append(param_map["arg_out"])
@@ -744,8 +785,7 @@ for json_domain in all_domains:
if "events" in json_domain:
for json_event in json_domain["events"]:
- if (not ("handlers" in json_event) or
- not ("browser" in json_event["handlers"])):
+ if json_domain["domain"] not in browser_domains_list:
continue
domain_empty = False
domain_needs_client = True
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index 5516fc78a46..a2f4cbd8082 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -256,6 +256,40 @@ Response EmulationHandler::SetVisibleSize(int width, int height) {
return Response::OK();
}
+Response EmulationHandler::ForceViewport(double x, double y, double scale) {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::ResetViewport() {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::ResetPageScaleFactor() {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::SetPageScaleFactor(double page_scale_factor) {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::SetScriptExecutionDisabled(bool disabled) {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::SetEmulatedMedia(const std::string& media) {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::SetCPUThrottlingRate(double rate) {
+ return Response::FallThrough();
+}
+
+Response EmulationHandler::SetVirtualTimePolicy(
+ const std::string& policy,
+ const int* budget) {
+ return Response::FallThrough();
+}
+
WebContentsImpl* EmulationHandler::GetWebContents() {
return host_ ?
static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) :
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.h b/chromium/content/browser/devtools/protocol/emulation_handler.h
index 1029002c4c5..8a98ce65c80 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.h
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.h
@@ -28,6 +28,7 @@ class EmulationHandler {
~EmulationHandler();
void SetRenderFrameHost(RenderFrameHostImpl* host);
+ void SetClient(std::unique_ptr<Client> client) { }
void Detached();
Response SetGeolocationOverride(double* latitude,
@@ -57,6 +58,15 @@ class EmulationHandler {
Response SetVisibleSize(int width, int height);
+ Response ForceViewport(double x, double y, double scale);
+ Response ResetViewport();
+ Response ResetPageScaleFactor();
+ Response SetPageScaleFactor(double page_scale_factor);
+ Response SetScriptExecutionDisabled(bool disabled);
+ Response SetEmulatedMedia(const std::string& media);
+ Response SetCPUThrottlingRate(double rate);
+ Response SetVirtualTimePolicy(const std::string& policy, const int* budget);
+
private:
WebContentsImpl* GetWebContents();
void UpdateTouchEventEmulationState();
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index 04be3a8e487..b963044209c 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -15,7 +15,7 @@
#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/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/point.h"
@@ -471,6 +471,14 @@ Response InputHandler::SynthesizeTapGesture(
return Response::OK();
}
+Response InputHandler::DispatchTouchEvent(
+ const std::string& type,
+ const std::vector<std::unique_ptr<base::DictionaryValue>>& touch_points,
+ const int* modifiers,
+ const double* timestamp) {
+ return Response::FallThrough();
+}
+
void InputHandler::SendSynthesizePinchGestureResponse(
DevToolsCommandId command_id,
SyntheticGesture::Result result) {
diff --git a/chromium/content/browser/devtools/protocol/input_handler.h b/chromium/content/browser/devtools/protocol/input_handler.h
index 6e548a5cbcb..691cad2f641 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.h
+++ b/chromium/content/browser/devtools/protocol/input_handler.h
@@ -16,10 +16,6 @@ namespace cc {
class CompositorFrameMetadata;
}
-namespace gfx {
-class Point;
-}
-
namespace content {
class RenderWidgetHostImpl;
@@ -98,6 +94,12 @@ class InputHandler {
const int* tap_count,
const std::string* gesture_source_type);
+ Response DispatchTouchEvent(
+ const std::string& type,
+ const std::vector<std::unique_ptr<base::DictionaryValue>>& touch_points,
+ const int* modifiers,
+ const double* timestamp);
+
private:
void SendSynthesizePinchGestureResponse(DevToolsCommandId command_id,
SyntheticGesture::Result result);
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc
index 9107fa93a4f..58a12fd9c29 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.cc
+++ b/chromium/content/browser/devtools/protocol/memory_handler.cc
@@ -7,6 +7,7 @@
#include "base/memory/memory_pressure_listener.h"
#include "base/strings/stringprintf.h"
#include "content/browser/memory/memory_pressure_controller_impl.h"
+#include "content/public/common/content_features.h"
namespace content {
namespace devtools {
@@ -18,6 +19,11 @@ MemoryHandler::~MemoryHandler() {}
MemoryHandler::Response MemoryHandler::SetPressureNotificationsSuppressed(
bool suppressed) {
+ if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
+ return Response::InvalidParams(
+ "Cannot enable/disable notifications when memory coordinator is "
+ "enabled");
+ }
content::MemoryPressureControllerImpl::GetInstance()
->SetPressureNotificationsSuppressedInAllProcesses(suppressed);
return Response::OK();
@@ -40,6 +46,13 @@ MemoryHandler::Response MemoryHandler::SimulatePressureNotification(
return Response::OK();
}
+MemoryHandler::Response MemoryHandler::GetDOMCounters(
+ int* documents,
+ int* nodes,
+ int* event_listeners) {
+ return Response::FallThrough();
+}
+
} // namespace memory
} // namespace devtools
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.h b/chromium/content/browser/devtools/protocol/memory_handler.h
index b080f50ea6b..3dd0b9306fe 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.h
+++ b/chromium/content/browser/devtools/protocol/memory_handler.h
@@ -20,6 +20,7 @@ class MemoryHandler {
typedef DevToolsProtocolClient::Response Response;
Response SetPressureNotificationsSuppressed(bool suppressed);
Response SimulatePressureNotification(const std::string& level);
+ Response GetDOMCounters(int* documents, int* nodes, int* event_listeners);
private:
DISALLOW_COPY_AND_ASSIGN(MemoryHandler);
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index 33d00f66c63..648d5a7ae82 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -255,7 +255,8 @@ class GetCookiesCommand {
typedef DevToolsProtocolClient::Response Response;
-NetworkHandler::NetworkHandler() : host_(nullptr), weak_factory_(this) {
+NetworkHandler::NetworkHandler()
+ : host_(nullptr), enabled_(false), weak_factory_(this) {
}
NetworkHandler::~NetworkHandler() {
@@ -269,6 +270,17 @@ void NetworkHandler::SetClient(std::unique_ptr<Client> client) {
client_.swap(client);
}
+Response NetworkHandler::Enable(const int* max_total_size,
+ const int* max_resource_size) {
+ enabled_ = true;
+ return Response::FallThrough();
+}
+
+Response NetworkHandler::Disable() {
+ enabled_ = false;
+ return Response::FallThrough();
+}
+
Response NetworkHandler::ClearBrowserCache() {
if (host_)
GetContentClient()->browser()->ClearCache(host_);
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
index 5f6c5b1cc3a..64c0b790e9d 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.h
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -26,6 +26,10 @@ class NetworkHandler {
void SetRenderFrameHost(RenderFrameHostImpl* host);
void SetClient(std::unique_ptr<Client> client);
+ Response Enable(const int* max_total_size,
+ const int* max_resource_size);
+ Response Disable();
+
Response ClearBrowserCache();
Response ClearBrowserCookies();
Response GetCookies(DevToolsCommandId command_id);
@@ -51,6 +55,8 @@ class NetworkHandler {
double upload_throughput,
const std::string* connection_type);
+ bool enabled() const { return enabled_; }
+
private:
void SendGetCookiesResponse(
DevToolsCommandId command_id,
@@ -60,6 +66,7 @@ class NetworkHandler {
RenderFrameHostImpl* host_;
std::unique_ptr<Client> client_;
+ bool enabled_;
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 7b5f47fb596..e1f72108bab 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -409,6 +409,62 @@ Response PageHandler::ProcessNavigation(const std::string& response,
return Response::InvalidParams("Unrecognized response");
}
+Response PageHandler::AddScriptToEvaluateOnLoad(const std::string& source,
+ std::string* identifier) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::RemoveScriptToEvaluateOnLoad(
+ const std::string& identifier) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::SetAutoAttachToCreatedPages(bool auto_attach) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::GetResourceTree(scoped_refptr<FrameResourceTree>* tree) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::GetResourceContent(DevToolsCommandId command_id,
+ const std::string& frame_id,
+ const std::string& url) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::SearchInResource(DevToolsCommandId command_id,
+ const std::string& frame_id,
+ const std::string& url,
+ const std::string& query,
+ bool* case_sensitive,
+ bool* is_regex) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::SetDocumentContent(const std::string& frame_id,
+ const std::string& html) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::ConfigureOverlay(const bool* is_suspended,
+ const std::string* message) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::GetAppManifest(
+ std::string* url,
+ std::vector<scoped_refptr<AppManifestError>>* errors,
+ std::string* data) {
+ return Response::FallThrough();
+}
+
+Response PageHandler::GetLayoutMetrics(
+ scoped_refptr<LayoutViewport>* layout_viewport,
+ scoped_refptr<VisualViewport>* visual_viewport) {
+ return Response::FallThrough();
+}
+
std::unique_ptr<PageNavigationThrottle>
PageHandler::CreateThrottleForNavigation(NavigationHandle* navigation_handle) {
if (!navigation_throttle_enabled_)
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index a8456df4271..86ddfeb9be0 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -85,6 +85,32 @@ class PageHandler : public NotificationObserver {
Response SetControlNavigations(bool enabled);
Response ProcessNavigation(const std::string& response, int navigation_id);
+ Response AddScriptToEvaluateOnLoad(const std::string& source,
+ std::string* identifier);
+ Response RemoveScriptToEvaluateOnLoad(const std::string& identifier);
+ Response SetAutoAttachToCreatedPages(bool auto_attach);
+ Response GetResourceTree(scoped_refptr<FrameResourceTree>* tree);
+ Response GetResourceContent(DevToolsCommandId command_id,
+ const std::string& frame_id,
+ const std::string& url);
+ Response SearchInResource(DevToolsCommandId command_id,
+ const std::string& frame_id,
+ const std::string& url,
+ const std::string& query,
+ bool* case_sensitive,
+ bool* is_regex);
+ Response SetDocumentContent(const std::string& frame_id,
+ const std::string& html);
+ Response ConfigureOverlay(const bool* is_suspended,
+ const std::string* message);
+ Response GetAppManifest(
+ std::string* url,
+ std::vector<scoped_refptr<AppManifestError>>* errors,
+ std::string* data);
+ Response GetLayoutMetrics(
+ scoped_refptr<LayoutViewport>* layout_viewport,
+ scoped_refptr<VisualViewport>* visual_viewport);
+
std::unique_ptr<PageNavigationThrottle> CreateThrottleForNavigation(
NavigationHandle* navigation_handle);
diff --git a/chromium/content/browser/devtools/protocol/schema_handler.cc b/chromium/content/browser/devtools/protocol/schema_handler.cc
index 93d3e1f9d64..a7cbe1ca168 100644
--- a/chromium/content/browser/devtools/protocol/schema_handler.cc
+++ b/chromium/content/browser/devtools/protocol/schema_handler.cc
@@ -23,9 +23,9 @@ Response SchemaHandler::GetDomains(
static const char* kDomains[] = {
"Inspector", "Memory", "Page", "Rendering", "Emulation", "Security",
"Network", "Database", "IndexedDB", "CacheStorage", "DOMStorage", "CSS",
- "ApplicationCache", "DOM", "IO", "DOMDebugger", "Worker", "ServiceWorker",
+ "ApplicationCache", "DOM", "IO", "DOMDebugger", "ServiceWorker",
"Input", "LayerTree", "DeviceOrientation", "Tracing", "Animation",
- "Accessibility", "Storage", "Log", "Browser", "Runtime", "Debugger",
+ "Accessibility", "Storage", "Log", "Runtime", "Debugger",
"Profiler", "HeapProfiler", "Schema", "Target"
};
for (size_t i = 0; i < arraysize(kDomains); ++i) {
diff --git a/chromium/content/browser/devtools/protocol/security_handler.cc b/chromium/content/browser/devtools/protocol/security_handler.cc
index 1b92427c9b3..d3efa82257f 100644
--- a/chromium/content/browser/devtools/protocol/security_handler.cc
+++ b/chromium/content/browser/devtools/protocol/security_handler.cc
@@ -23,17 +23,17 @@ typedef DevToolsProtocolClient::Response Response;
namespace {
std::string SecurityStyleToProtocolSecurityState(
- SecurityStyle security_style) {
+ blink::WebSecurityStyle security_style) {
switch (security_style) {
- case SECURITY_STYLE_UNKNOWN:
+ case blink::WebSecurityStyleUnknown:
return kSecurityStateUnknown;
- case SECURITY_STYLE_UNAUTHENTICATED:
+ case blink::WebSecurityStyleUnauthenticated:
return kSecurityStateNeutral;
- case SECURITY_STYLE_AUTHENTICATION_BROKEN:
+ case blink::WebSecurityStyleAuthenticationBroken:
return kSecurityStateInsecure;
- case SECURITY_STYLE_WARNING:
+ case blink::WebSecurityStyleWarning:
return kSecurityStateWarning;
- case SECURITY_STYLE_AUTHENTICATED:
+ case blink::WebSecurityStyleAuthenticated:
return kSecurityStateSecure;
default:
NOTREACHED();
@@ -78,7 +78,7 @@ void SecurityHandler::AttachToRenderFrameHost() {
// Send an initial SecurityStyleChanged event.
DCHECK(enabled_);
SecurityStyleExplanations security_style_explanations;
- SecurityStyle security_style =
+ blink::WebSecurityStyle security_style =
web_contents->GetDelegate()->GetSecurityStyle(
web_contents, &security_style_explanations);
SecurityStyleChanged(security_style, security_style_explanations);
@@ -91,7 +91,7 @@ void SecurityHandler::SetRenderFrameHost(RenderFrameHost* host) {
}
void SecurityHandler::SecurityStyleChanged(
- SecurityStyle security_style,
+ blink::WebSecurityStyle security_style,
const SecurityStyleExplanations& security_style_explanations) {
DCHECK(enabled_);
diff --git a/chromium/content/browser/devtools/protocol/security_handler.h b/chromium/content/browser/devtools/protocol/security_handler.h
index 5f9e979ca93..df41beb1d1b 100644
--- a/chromium/content/browser/devtools/protocol/security_handler.h
+++ b/chromium/content/browser/devtools/protocol/security_handler.h
@@ -9,7 +9,6 @@
#include "content/browser/devtools/devtools_protocol_handler.h"
#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/security_style.h"
namespace content {
namespace devtools {
@@ -34,7 +33,7 @@ class SecurityHandler : public WebContentsObserver {
// WebContentsObserver overrides
void SecurityStyleChanged(
- SecurityStyle security_style,
+ blink::WebSecurityStyle security_style,
const SecurityStyleExplanations& security_style_explanations) override;
std::unique_ptr<Client> client_;
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index d87a7de72a5..254a4ac1f18 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/devtools/protocol/target_handler.h"
+#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -83,6 +84,14 @@ ServiceWorkerDevToolsAgentHost::Map GetMatchingServiceWorkers(
return result;
}
+scoped_refptr<TargetInfo> CreateInfo(DevToolsAgentHost* host) {
+ return TargetInfo::Create()
+ ->set_target_id(host->GetId())
+ ->set_title(host->GetTitle())
+ ->set_url(host->GetURL().spec())
+ ->set_type(host->GetType());
+}
+
} // namespace
TargetHandler::TargetHandler()
@@ -109,6 +118,9 @@ void TargetHandler::SetClient(std::unique_ptr<Client> client) {
void TargetHandler::Detached() {
SetAutoAttach(false, false);
SetDiscoverTargets(false);
+ for (const auto& id_host : attached_hosts_)
+ id_host.second->DetachClient(this);
+ attached_hosts_.clear();
}
void TargetHandler::UpdateServiceWorkers() {
@@ -175,29 +187,30 @@ void TargetHandler::ReattachTargetsOfType(
if (pair.second->GetType() == type &&
new_hosts.find(pair.first) == new_hosts.end()) {
DetachFromTargetInternal(pair.second.get());
- TargetRemovedInternal(pair.second.get());
}
}
for (const auto& pair : new_hosts) {
- if (old_hosts.find(pair.first) == old_hosts.end()) {
- TargetCreatedInternal(pair.second.get());
+ if (old_hosts.find(pair.first) == old_hosts.end())
AttachToTargetInternal(pair.second.get(), waiting_for_debugger);
- }
}
}
void TargetHandler::TargetCreatedInternal(DevToolsAgentHost* host) {
+ if (reported_hosts_.find(host->GetId()) != reported_hosts_.end())
+ return;
client_->TargetCreated(
- TargetCreatedParams::Create()->set_target_info(
- TargetInfo::Create()->set_target_id(host->GetId())
- ->set_title(host->GetTitle())
- ->set_url(host->GetURL().spec())
- ->set_type(host->GetType())));
+ TargetCreatedParams::Create()->set_target_info(CreateInfo(host)));
+ reported_hosts_[host->GetId()] = host;
}
-void TargetHandler::TargetRemovedInternal(DevToolsAgentHost* host) {
- client_->TargetRemoved(TargetRemovedParams::Create()
+void TargetHandler::TargetDestroyedInternal(
+ DevToolsAgentHost* host) {
+ auto it = reported_hosts_.find(host->GetId());
+ if (it == reported_hosts_.end())
+ return;
+ client_->TargetDestroyed(TargetDestroyedParams::Create()
->set_target_id(host->GetId()));
+ reported_hosts_.erase(it);
}
bool TargetHandler::AttachToTargetInternal(
@@ -206,7 +219,7 @@ bool TargetHandler::AttachToTargetInternal(
return false;
attached_hosts_[host->GetId()] = host;
client_->AttachedToTarget(AttachedToTargetParams::Create()
- ->set_target_id(host->GetId())
+ ->set_target_info(CreateInfo(host))
->set_waiting_for_debugger(waiting_for_debugger));
return true;
}
@@ -227,7 +240,14 @@ Response TargetHandler::SetDiscoverTargets(bool discover) {
if (discover_ == discover)
return Response::OK();
discover_ = discover;
- // TODO(dgozman): observe all agent hosts here.
+ if (discover_) {
+ DevToolsAgentHost::AddObserver(this);
+ } else {
+ DevToolsAgentHost::RemoveObserver(this);
+ RawHostsMap copy = reported_hosts_;
+ for (const auto& id_host : copy)
+ TargetDestroyedInternal(id_host.second);
+ }
return Response::OK();
}
@@ -235,7 +255,7 @@ Response TargetHandler::SetAutoAttach(
bool auto_attach, bool wait_for_debugger_on_start) {
wait_for_debugger_on_start_ = wait_for_debugger_on_start;
if (auto_attach_ == auto_attach)
- return Response::OK();
+ return Response::FallThrough();
auto_attach_ = auto_attach;
if (auto_attach_) {
ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
@@ -247,7 +267,7 @@ Response TargetHandler::SetAutoAttach(
ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeFrame, false);
ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeServiceWorker, false);
}
- return Response::OK();
+ return Response::FallThrough();
}
Response TargetHandler::SetAttachToFrames(bool value) {
@@ -263,12 +283,18 @@ Response TargetHandler::SetAttachToFrames(bool value) {
return Response::OK();
}
+Response TargetHandler::SetRemoteLocations(
+ const std::vector<std::unique_ptr<base::DictionaryValue>>& locations) {
+ return Response::ServerError("Not supported");
+}
+
Response TargetHandler::AttachToTarget(const std::string& target_id,
bool* out_success) {
- scoped_refptr<DevToolsAgentHost> agent_host(
- DevToolsAgentHost::GetForId(target_id));
+ // TODO(dgozman): only allow reported hosts.
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(target_id);
if (!agent_host)
- return Response::InvalidParams("No target with such id");
+ return Response::ServerError("No target with given id found");
*out_success = AttachToTargetInternal(agent_host.get(), false);
return Response::OK();
}
@@ -277,7 +303,8 @@ Response TargetHandler::DetachFromTarget(const std::string& target_id) {
auto it = attached_hosts_.find(target_id);
if (it == attached_hosts_.end())
return Response::InternalError("Not attached to the target");
- DetachFromTargetInternal(it->second.get());
+ DevToolsAgentHost* agent_host = it->second.get();
+ DetachFromTargetInternal(agent_host);
return Response::OK();
}
@@ -286,7 +313,7 @@ Response TargetHandler::SendMessageToTarget(
const std::string& message) {
auto it = attached_hosts_.find(target_id);
if (it == attached_hosts_.end())
- return Response::InternalError("Not attached to the target");
+ return Response::FallThrough();
it->second->DispatchProtocolMessage(this, message);
return Response::OK();
}
@@ -294,27 +321,68 @@ Response TargetHandler::SendMessageToTarget(
Response TargetHandler::GetTargetInfo(
const std::string& target_id,
scoped_refptr<TargetInfo>* target_info) {
+ // TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host(
DevToolsAgentHost::GetForId(target_id));
if (!agent_host)
- return Response::InvalidParams("No target with such id");
- *target_info = TargetInfo::Create()
- ->set_target_id(agent_host->GetId())
- ->set_type(agent_host->GetType())
- ->set_title(agent_host->GetTitle())
- ->set_url(agent_host->GetURL().spec());
+ return Response::InvalidParams("No target with given id found");
+ *target_info = CreateInfo(agent_host.get());
return Response::OK();
}
Response TargetHandler::ActivateTarget(const std::string& target_id) {
+ // TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host(
DevToolsAgentHost::GetForId(target_id));
if (!agent_host)
- return Response::InvalidParams("No target with such id");
+ return Response::InvalidParams("No target with given id found");
agent_host->Activate();
return Response::OK();
}
+Response TargetHandler::CloseTarget(const std::string& target_id,
+ bool* out_success) {
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(target_id);
+ if (!agent_host)
+ return Response::ServerError("No target with given id found");
+ *out_success = agent_host->Close();
+ return Response::OK();
+}
+
+Response TargetHandler::CreateBrowserContext(std::string* out_context_id) {
+ return Response::ServerError("Not supported");
+}
+
+Response TargetHandler::DisposeBrowserContext(const std::string& context_id,
+ bool* out_success) {
+ return Response::ServerError("Not supported");
+}
+
+Response TargetHandler::CreateTarget(const std::string& url,
+ const int* width,
+ const int* height,
+ const std::string* context_id,
+ std::string* out_target_id) {
+ DevToolsManagerDelegate* delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (!delegate)
+ return Response::ServerError("Not supported");
+ scoped_refptr<content::DevToolsAgentHost> agent_host =
+ delegate->CreateNewTarget(GURL(url));
+ if (!agent_host)
+ return Response::ServerError("Not supported");
+ *out_target_id = agent_host->GetId();
+ return Response::OK();
+}
+
+Response TargetHandler::GetTargets(
+ std::vector<scoped_refptr<TargetInfo>>* target_infos) {
+ for (const auto& host : DevToolsAgentHost::GetOrCreateAll())
+ target_infos->push_back(CreateInfo(host.get()));
+ return Response::OK();
+}
+
// ---------------- DevToolsAgentHostClient ----------------
void TargetHandler::DispatchProtocolMessage(
@@ -336,7 +404,22 @@ void TargetHandler::AgentHostClosed(
client_->DetachedFromTarget(DetachedFromTargetParams::Create()->
set_target_id(host->GetId()));
attached_hosts_.erase(host->GetId());
- TargetRemovedInternal(host);
+}
+
+// -------------- DevToolsAgentHostObserver -----------------
+
+bool TargetHandler::ShouldForceDevToolsAgentHostCreation() {
+ return true;
+}
+
+void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) {
+ DCHECK(attached_hosts_.find(agent_host->GetId()) == attached_hosts_.end());
+ TargetCreatedInternal(agent_host);
+}
+
+void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) {
+ DCHECK(attached_hosts_.find(agent_host->GetId()) == attached_hosts_.end());
+ TargetDestroyedInternal(agent_host);
}
// -------- ServiceWorkerDevToolsManager::Observer ----------
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index 9b7bcaba3a5..c37c6022849 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -11,6 +11,7 @@
#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/public/browser/devtools_agent_host_client.h"
+#include "content/public/browser/devtools_agent_host_observer.h"
namespace content {
@@ -20,7 +21,8 @@ namespace devtools {
namespace target {
class TargetHandler : public DevToolsAgentHostClient,
- public ServiceWorkerDevToolsManager::Observer {
+ public ServiceWorkerDevToolsManager::Observer,
+ public DevToolsAgentHostObserver {
public:
using Response = DevToolsProtocolClient::Response;
@@ -38,6 +40,8 @@ class TargetHandler : public DevToolsAgentHostClient,
Response SetDiscoverTargets(bool discover);
Response SetAutoAttach(bool auto_attach, bool wait_for_debugger_on_start);
Response SetAttachToFrames(bool value);
+ Response SetRemoteLocations(
+ const std::vector<std::unique_ptr<base::DictionaryValue>>&);
Response AttachToTarget(const std::string& target_id, bool* out_success);
Response DetachFromTarget(const std::string& target_id);
Response SendMessageToTarget(const std::string& target_id,
@@ -45,16 +49,27 @@ class TargetHandler : public DevToolsAgentHostClient,
Response GetTargetInfo(const std::string& target_id,
scoped_refptr<TargetInfo>* target_info);
Response ActivateTarget(const std::string& target_id);
+ Response CloseTarget(const std::string& target_id, bool* out_success);
+ Response CreateBrowserContext(std::string* out_context_id);
+ Response DisposeBrowserContext(const std::string& context_id,
+ bool* out_success);
+ Response CreateTarget(const std::string& url,
+ const int* width,
+ const int* height,
+ const std::string* context_id,
+ std::string* out_target_id);
+ Response GetTargets(std::vector<scoped_refptr<TargetInfo>>* target_infos);
private:
using HostsMap = std::map<std::string, scoped_refptr<DevToolsAgentHost>>;
+ using RawHostsMap = std::map<std::string, DevToolsAgentHost*>;
void UpdateServiceWorkers(bool waiting_for_debugger);
void ReattachTargetsOfType(const HostsMap& new_hosts,
const std::string& type,
bool waiting_for_debugger);
void TargetCreatedInternal(DevToolsAgentHost* host);
- void TargetRemovedInternal(DevToolsAgentHost* host);
+ void TargetDestroyedInternal(DevToolsAgentHost* host);
bool AttachToTargetInternal(DevToolsAgentHost* host,
bool waiting_for_debugger);
void DetachFromTargetInternal(DevToolsAgentHost* host);
@@ -66,6 +81,11 @@ class TargetHandler : public DevToolsAgentHostClient,
void WorkerVersionDoomed(ServiceWorkerDevToolsAgentHost* host) override;
void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override;
+ // DevToolsAgentHostObserver implementation.
+ bool ShouldForceDevToolsAgentHostCreation() override;
+ void DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) override;
+ void DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) override;
+
// DevToolsAgentHostClient implementation.
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) override;
@@ -80,6 +100,7 @@ class TargetHandler : public DevToolsAgentHostClient,
RenderFrameHostImpl* render_frame_host_;
HostsMap attached_hosts_;
std::set<GURL> frame_urls_;
+ RawHostsMap reported_hosts_;
DISALLOW_COPY_AND_ASSIGN(TargetHandler);
};
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc
index def799312e3..c688462dcc4 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc
@@ -4,7 +4,7 @@
#include "content/browser/devtools/protocol/tethering_handler.h"
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_address.h"
@@ -247,8 +247,7 @@ class TetheringHandler::TetheringImpl {
base::WeakPtr<TetheringHandler> handler_;
CreateServerSocketCallback socket_callback_;
- typedef std::map<uint16_t, BoundSocket*> BoundSockets;
- BoundSockets bound_sockets_;
+ std::map<uint16_t, std::unique_ptr<BoundSocket>> bound_sockets_;
};
TetheringHandler::TetheringImpl::TetheringImpl(
@@ -258,9 +257,7 @@ TetheringHandler::TetheringImpl::TetheringImpl(
socket_callback_(socket_callback) {
}
-TetheringHandler::TetheringImpl::~TetheringImpl() {
- base::STLDeleteValues(&bound_sockets_);
-}
+TetheringHandler::TetheringImpl::~TetheringImpl() = default;
void TetheringHandler::TetheringImpl::Bind(DevToolsCommandId command_id,
uint16_t port) {
@@ -271,14 +268,14 @@ void TetheringHandler::TetheringImpl::Bind(DevToolsCommandId command_id,
BoundSocket::AcceptedCallback callback = base::Bind(
&TetheringHandler::TetheringImpl::Accepted, base::Unretained(this));
- std::unique_ptr<BoundSocket> bound_socket(
- new BoundSocket(callback, socket_callback_));
+ std::unique_ptr<BoundSocket> bound_socket =
+ base::MakeUnique<BoundSocket>(callback, socket_callback_);
if (!bound_socket->Listen(port)) {
SendInternalError(command_id, "Could not bind port");
return;
}
- bound_sockets_[port] = bound_socket.release();
+ bound_sockets_[port] = std::move(bound_socket);
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -287,13 +284,12 @@ void TetheringHandler::TetheringImpl::Bind(DevToolsCommandId command_id,
void TetheringHandler::TetheringImpl::Unbind(DevToolsCommandId command_id,
uint16_t port) {
- BoundSockets::iterator it = bound_sockets_.find(port);
+ auto it = bound_sockets_.find(port);
if (it == bound_sockets_.end()) {
SendInternalError(command_id, "Port is not bound");
return;
}
- delete it->second;
bound_sockets_.erase(it);
BrowserThread::PostTask(
BrowserThread::UI,
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.h b/chromium/content/browser/devtools/protocol/tethering_handler.h
index 228ff904c12..0fb9904efe3 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.h
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.h
@@ -9,7 +9,9 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
namespace net {
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index 019cd9c3ebb..5a235be20cd 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -20,7 +20,6 @@
#include "content/public/browser/tracing_controller.h"
namespace base {
-class RefCountedString;
class Timer;
}
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
index 6b1f7a9c3f8..b5cda566aef 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -17,7 +17,6 @@ namespace {
const char kCustomTraceConfigString[] =
"{"
"\"enable_argument_filter\":true,"
- "\"enable_sampling\":true,"
"\"enable_systrace\":true,"
"\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
"\"included_categories\":[\"included\","
@@ -38,7 +37,6 @@ const char kCustomTraceConfigString[] =
const char kCustomTraceConfigStringDevToolsStyle[] =
"{"
"\"enableArgumentFilter\":true,"
- "\"enableSampling\":true,"
"\"enableSystrace\":true,"
"\"excludedCategories\":[\"excluded\",\"exc_pattern*\"],"
"\"includedCategories\":[\"included\","
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
new file mode 100644
index 00000000000..667c3384edd
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -0,0 +1,30 @@
+{
+ "use_snake_file_names": true,
+ "use_title_case_methods": true,
+
+ "protocol": {
+ "package": "content/browser/devtools/protocol",
+ "output": "protocol",
+ "namespace": ["content", "protocol"],
+ "export_macro": "CONTENT_EXPORT",
+ "export_header": "content/common/content_export.h",
+ "options": [
+ {
+ "domain": "IO",
+ "async": ["read"]
+ },
+ {
+ "domain": "Tracing",
+ "async": ["start", "end"]
+ }
+ ]
+ },
+
+ "lib": {
+ "package": "content/browser/devtools/protocol",
+ "output": "protocol",
+ "string_header": "content/browser/devtools/protocol_string.h",
+ "export_macro": "CONTENT_EXPORT",
+ "export_header": "content/common/content_export.h"
+ }
+}
diff --git a/chromium/content/browser/devtools/protocol_string.cc b/chromium/content/browser/devtools/protocol_string.cc
new file mode 100644
index 00000000000..f5de9499d45
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol_string.cc
@@ -0,0 +1,107 @@
+// 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/protocol_string.h"
+
+#include "base/json/json_reader.h"
+#include "base/values.h"
+#include "content/browser/devtools/protocol/protocol.h"
+
+namespace content {
+namespace {
+
+std::unique_ptr<protocol::Value> toProtocolValue(
+ const base::Value* value, int depth) {
+ if (!value || !depth)
+ return nullptr;
+ if (value->IsType(base::Value::TYPE_NULL))
+ return protocol::Value::null();
+ if (value->IsType(base::Value::TYPE_BOOLEAN)) {
+ bool inner;
+ value->GetAsBoolean(&inner);
+ return protocol::FundamentalValue::create(inner);
+ }
+ if (value->IsType(base::Value::TYPE_INTEGER)) {
+ int inner;
+ value->GetAsInteger(&inner);
+ return protocol::FundamentalValue::create(inner);
+ }
+ if (value->IsType(base::Value::TYPE_DOUBLE)) {
+ double inner;
+ value->GetAsDouble(&inner);
+ return protocol::FundamentalValue::create(inner);
+ }
+ if (value->IsType(base::Value::TYPE_STRING)) {
+ std::string inner;
+ value->GetAsString(&inner);
+ return protocol::StringValue::create(inner);
+ }
+ if (value->IsType(base::Value::TYPE_LIST)) {
+ const base::ListValue* list = nullptr;
+ value->GetAsList(&list);
+ std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create();
+ for (size_t i = 0; i < list->GetSize(); i++) {
+ const base::Value* item = nullptr;
+ list->Get(i, &item);
+ std::unique_ptr<protocol::Value> converted =
+ toProtocolValue(item, depth - 1);
+ if (converted)
+ result->pushValue(std::move(converted));
+ }
+ return std::move(result);
+ }
+ if (value->IsType(base::Value::TYPE_DICTIONARY)) {
+ const base::DictionaryValue* dictionary = nullptr;
+ value->GetAsDictionary(&dictionary);
+ std::unique_ptr<protocol::DictionaryValue> result =
+ protocol::DictionaryValue::create();
+ for (base::DictionaryValue::Iterator it(*dictionary);
+ !it.IsAtEnd(); it.Advance()) {
+ std::unique_ptr<protocol::Value> converted =
+ toProtocolValue(&it.value(), depth - 1);
+ if (converted)
+ result->setValue(it.key(), std::move(converted));
+ }
+ return std::move(result);
+ }
+ return nullptr;
+}
+
+} // namespace
+
+namespace protocol {
+
+// static
+std::unique_ptr<protocol::Value> StringUtil::parseJSON(
+ const std::string& json) {
+ std::unique_ptr<base::Value> value = base::JSONReader::Read(json);
+ return toProtocolValue(value.get(), 1000);
+}
+
+StringBuilder::StringBuilder() {}
+
+StringBuilder::~StringBuilder() {}
+
+void StringBuilder::append(const std::string& s) {
+ string_ += s;
+}
+
+void StringBuilder::append(char c) {
+ string_ += c;
+}
+
+void StringBuilder::append(const char* characters, size_t length) {
+ string_.append(characters, length);
+}
+
+std::string StringBuilder::toString() {
+ return string_;
+}
+
+void StringBuilder::reserveCapacity(size_t capacity) {
+ string_.reserve(capacity);
+}
+
+} // namespace protocol
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol_string.h b/chromium/content/browser/devtools/protocol_string.h
new file mode 100644
index 00000000000..8541aba1ae7
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol_string.h
@@ -0,0 +1,58 @@
+// 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_PROTOCOL_STRING_H
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_STRING_H
+
+#include <memory>
+#include <string>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/common/content_export.h"
+
+namespace content {
+namespace protocol {
+
+class Value;
+
+using String = std::string;
+
+class CONTENT_EXPORT StringBuilder {
+ public:
+ StringBuilder();
+ ~StringBuilder();
+ void append(const std::string&);
+ void append(char);
+ void append(const char*, size_t);
+ std::string toString();
+ void reserveCapacity(size_t);
+
+ private:
+ std::string string_;
+};
+
+class CONTENT_EXPORT StringUtil {
+ public:
+ static String substring(const String& s, unsigned pos, unsigned len) {
+ return s.substr(pos, len);
+ }
+ static String fromInteger(int number) {
+ return base::IntToString(number);
+ }
+ static String fromDouble(double number) {
+ return base::DoubleToString(number);
+ }
+ static const size_t kNotFound = static_cast<size_t>(-1);
+ static void builderReserve(StringBuilder& builder, unsigned capacity) {
+ builder.reserveCapacity(capacity);
+ }
+ static std::unique_ptr<protocol::Value> parseJSON(const String&);
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_STRING_H
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 a3985bf3c3a..cc99610ca36 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -16,8 +16,8 @@
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_protocol_handler.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"
@@ -150,7 +150,7 @@ RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach() {
host_->Send(new DevToolsAgentMsg_Attach(
- host_->GetRoutingID(), agent_->GetId(), agent_->session_id()));
+ host_->GetRoutingID(), agent_->GetId(), agent_->session()->session_id()));
GrantPolicy();
attached_ = true;
}
@@ -160,7 +160,7 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
if (old)
chunk_processor_.set_state_cookie(old->chunk_processor_.state_cookie());
host_->Send(new DevToolsAgentMsg_Reattach(
- host_->GetRoutingID(), agent_->GetId(), agent_->session_id(),
+ host_->GetRoutingID(), agent_->GetId(), agent_->session()->session_id(),
chunk_processor_.state_cookie()));
if (old) {
for (const auto& pair : old->sent_messages_) {
@@ -372,10 +372,27 @@ RenderFrameDevToolsAgentHost::CreateThrottleForNavigation(
return nullptr;
}
+// static
+bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(
+ FrameTreeNode* frame_tree_node) {
+ RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
+ if (!agent_host)
+ return false;
+ return agent_host->network_handler_->enabled();
+}
+
+// static
+void RenderFrameDevToolsAgentHost::WebContentsCreated(
+ WebContents* web_contents) {
+ if (ShouldForceCreation()) {
+ // Force agent host.
+ DevToolsAgentHost::GetOrCreateFor(web_contents);
+ }
+}
+
RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
RenderFrameHostImpl* host)
: DevToolsAgentHostImpl(base::GenerateGUID()),
- browser_handler_(new devtools::browser::BrowserHandler()),
dom_handler_(new devtools::dom::DOMHandler()),
input_handler_(new devtools::input::InputHandler()),
inspector_handler_(new devtools::inspector::InspectorHandler()),
@@ -400,7 +417,6 @@ RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
pending_handle_(nullptr),
frame_tree_node_(host->frame_tree_node()) {
DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
- dispatcher->SetBrowserHandler(browser_handler_.get());
dispatcher->SetDOMHandler(dom_handler_.get());
dispatcher->SetInputHandler(input_handler_.get());
dispatcher->SetInspectorHandler(inspector_handler_.get());
@@ -433,6 +449,7 @@ RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
g_instances.Get().push_back(this);
AddRef(); // Balanced in RenderFrameHostDestroyed.
+ NotifyCreated();
}
void RenderFrameDevToolsAgentHost::SetPending(RenderFrameHostImpl* host) {
@@ -502,29 +519,33 @@ bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
const std::string& message) {
int call_id = 0;
std::string method;
- if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id,
- &method))
+ if (protocol_handler_->HandleOptionalMessage(session()->session_id(), message,
+ &call_id, &method))
return true;
if (!navigating_handles_.empty()) {
DCHECK(IsBrowserSideNavigationEnabled());
in_navigation_protocol_message_buffer_[call_id] =
- { session_id(), method, message };
+ { session()->session_id(), method, message };
return true;
}
- if (current_)
- current_->DispatchProtocolMessage(session_id(), call_id, method, message);
- if (pending_)
- pending_->DispatchProtocolMessage(session_id(), call_id, method, message);
+ if (current_) {
+ current_->DispatchProtocolMessage(
+ session()->session_id(), call_id, method, message);
+ }
+ if (pending_) {
+ pending_->DispatchProtocolMessage(
+ session()->session_id(), call_id, method, message);
+ }
return true;
}
void RenderFrameDevToolsAgentHost::InspectElement(int x, int y) {
if (current_)
- current_->InspectElement(session_id(), x, y);
+ current_->InspectElement(session()->session_id(), x, y);
if (pending_)
- pending_->InspectElement(session_id(), x, y);
+ pending_->InspectElement(session()->session_id(), x, y);
}
void RenderFrameDevToolsAgentHost::OnClientAttached() {
@@ -533,17 +554,12 @@ void RenderFrameDevToolsAgentHost::OnClientAttached() {
frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
CreatePowerSaveBlocker();
-
- // TODO(kaznacheev): Move this call back to DevToolsManager when
- // extensions::ProcessManager no longer relies on this notification.
- DevToolsAgentHostImpl::NotifyCallbacks(this, true);
}
void RenderFrameDevToolsAgentHost::OnClientDetached() {
#if defined(OS_ANDROID)
power_save_blocker_.reset();
#endif
- browser_handler_->Detached();
if (emulation_handler_)
emulation_handler_->Detached();
if (page_handler_)
@@ -553,10 +569,6 @@ void RenderFrameDevToolsAgentHost::OnClientDetached() {
tracing_handler_->Detached();
frame_trace_recorder_.reset();
in_navigation_protocol_message_buffer_.clear();
-
- // TODO(kaznacheev): Move this call back to DevToolsManager when
- // extensions::ProcessManager no longer relies on this notification.
- DevToolsAgentHostImpl::NotifyCallbacks(this, false);
}
RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
@@ -569,8 +581,14 @@ RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
void RenderFrameDevToolsAgentHost::ReadyToCommitNavigation(
NavigationHandle* navigation_handle) {
- // ReadyToCommitNavigation should only be called in PlzNavigate.
- DCHECK(IsBrowserSideNavigationEnabled());
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
+ // TODO(clamy): Switch RenderFrameDevToolsAgentHost to always buffer messages
+ // until ReadyToCommitNavigation is called, now that it is also called in
+ // non-PlzNavigate mode.
+ if (!IsBrowserSideNavigationEnabled())
+ return;
// If the navigation is not tracked, return;
if (navigating_handles_.count(navigation_handle) == 0)
@@ -594,6 +612,9 @@ void RenderFrameDevToolsAgentHost::ReadyToCommitNavigation(
void RenderFrameDevToolsAgentHost::DidFinishNavigation(
NavigationHandle* navigation_handle) {
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
if (!IsBrowserSideNavigationEnabled())
return;
@@ -626,6 +647,9 @@ void RenderFrameDevToolsAgentHost::DidFinishNavigation(
void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
if (IsBrowserSideNavigationEnabled())
return;
@@ -659,6 +683,9 @@ void RenderFrameDevToolsAgentHost::AboutToNavigate(
void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
target_handler_->UpdateFrames();
if (IsBrowserSideNavigationEnabled())
@@ -816,6 +843,9 @@ void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
RenderFrameHost* render_frame_host,
const GURL& url,
ui::PageTransition transition_type) {
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
if (IsBrowserSideNavigationEnabled())
return;
if (pending_ && pending_->host() == render_frame_host)
@@ -895,6 +925,9 @@ void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
}
void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
+ // CommitPending may destruct |this|.
+ scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
+
DCHECK(!current_);
DCHECK(!pending_);
RenderFrameHostImpl* host =
@@ -927,8 +960,11 @@ std::string RenderFrameDevToolsAgentHost::GetParentId() {
std::string RenderFrameDevToolsAgentHost::GetType() {
DevToolsManager* manager = DevToolsManager::GetInstance();
- if (manager->delegate())
- return manager->delegate()->GetTargetType(current_->host());
+ if (manager->delegate() && current_) {
+ std::string result = manager->delegate()->GetTargetType(current_->host());
+ if (!result.empty())
+ return result;
+ }
if (IsChildFrame())
return kTypeFrame;
return kTypePage;
@@ -936,20 +972,20 @@ std::string RenderFrameDevToolsAgentHost::GetType() {
std::string RenderFrameDevToolsAgentHost::GetTitle() {
DevToolsManager* manager = DevToolsManager::GetInstance();
- std::string result;
- if (manager->delegate())
- result = manager->delegate()->GetTargetTitle(current_->host());
- if (!result.empty())
- return result;
+ if (manager->delegate() && current_) {
+ std::string result = manager->delegate()->GetTargetTitle(current_->host());
+ if (!result.empty())
+ return result;
+ }
content::WebContents* web_contents = GetWebContents();
if (web_contents)
- result = base::UTF16ToUTF8(web_contents->GetTitle());
+ return base::UTF16ToUTF8(web_contents->GetTitle());
return GetURL().spec();
}
std::string RenderFrameDevToolsAgentHost::GetDescription() {
DevToolsManager* manager = DevToolsManager::GetInstance();
- if (manager->delegate())
+ if (manager->delegate() && current_)
return manager->delegate()->GetTargetDescription(current_->host());
return "";
}
@@ -1021,6 +1057,21 @@ void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
}
}
+void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
+ RenderFrameHost* frame_host,
+ cc::CompositorFrameMetadata frame_metadata) {
+ scoped_refptr<RenderFrameDevToolsAgentHost> dtah(FindAgentHost(frame_host));
+ if (dtah) {
+ // Unblock the compositor.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
+ dtah.get(),
+ base::Passed(std::move(frame_metadata))));
+ }
+}
+
void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
cc::CompositorFrameMetadata frame_metadata) {
if (page_handler_)
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 2a1350f04fd..984c0cba74e 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -40,7 +40,6 @@ class NavigationThrottle;
class RenderFrameHostImpl;
namespace devtools {
-namespace browser { class BrowserHandler; }
namespace dom { class DOMHandler; }
namespace emulation { class EmulationHandler; }
namespace input { class InputHandler; }
@@ -69,8 +68,12 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static void OnBeforeNavigation(NavigationHandle* navigation_handle);
static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
NavigationHandle* navigation_handle);
+ static bool IsNetworkHandlerEnabled(FrameTreeNode* frame_tree_node);
- void SynchronousSwapCompositorFrame(
+ static void WebContentsCreated(WebContents* web_contents);
+
+ static void SignalSynchronousSwapCompositorFrame(
+ RenderFrameHost* frame_host,
cc::CompositorFrameMetadata frame_metadata);
bool HasRenderFrameHost(RenderFrameHost* host);
@@ -166,6 +169,9 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void CreatePowerSaveBlocker();
+ void SynchronousSwapCompositorFrame(
+ cc::CompositorFrameMetadata frame_metadata);
+
class FrameHostHolder;
std::unique_ptr<FrameHostHolder> current_;
@@ -174,7 +180,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
// Stores per-host state between DisconnectWebContents and ConnectWebContents.
std::unique_ptr<FrameHostHolder> disconnected_;
- std::unique_ptr<devtools::browser::BrowserHandler> browser_handler_;
std::unique_ptr<devtools::dom::DOMHandler> dom_handler_;
std::unique_ptr<devtools::input::InputHandler> input_handler_;
std::unique_ptr<devtools::inspector::InspectorHandler> inspector_handler_;
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 8337def3feb..0ac09f8b31c 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -63,6 +63,7 @@ ServiceWorkerDevToolsAgentHost::ServiceWorkerDevToolsAgentHost(
: base::Time()) {
DevToolsProtocolDispatcher* dispatcher = protocol_handler()->dispatcher();
dispatcher->SetNetworkHandler(network_handler_.get());
+ NotifyCreated();
}
std::string ServiceWorkerDevToolsAgentHost::GetType() {
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.cc b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
index e7c76d8e9b6..5febfff097b 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
@@ -89,7 +89,8 @@ bool ServiceWorkerDevToolsManager::WorkerCreated(
new ServiceWorkerDevToolsAgentHost(id, service_worker_id,
is_installed_version);
workers_[id] = host.get();
- FOR_EACH_OBSERVER(Observer, observer_list_, WorkerCreated(host.get()));
+ for (auto& observer : observer_list_)
+ observer.WorkerCreated(host.get());
if (debug_service_worker_on_start_)
host->PauseForDebugOnStart();
return host->IsPausedForDebugOnStart();
@@ -114,8 +115,8 @@ void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerReadyForInspection();
- FOR_EACH_OBSERVER(Observer, observer_list_,
- WorkerReadyForInspection(host.get()));
+ for (auto& observer : observer_list_)
+ observer.WorkerReadyForInspection(host.get());
// Then bring up UI for the ones not picked by other clients.
if (host->IsPausedForDebugOnStart() && !host->IsAttached())
@@ -131,8 +132,8 @@ void ServiceWorkerDevToolsManager::WorkerVersionInstalled(int worker_process_id,
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerVersionInstalled();
- FOR_EACH_OBSERVER(Observer, observer_list_,
- WorkerVersionInstalled(host.get()));
+ for (auto& observer : observer_list_)
+ observer.WorkerVersionInstalled(host.get());
}
void ServiceWorkerDevToolsManager::WorkerVersionDoomed(int worker_process_id,
@@ -144,7 +145,8 @@ void ServiceWorkerDevToolsManager::WorkerVersionDoomed(int worker_process_id,
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerVersionDoomed();
- FOR_EACH_OBSERVER(Observer, observer_list_, WorkerVersionDoomed(host.get()));
+ for (auto& observer : observer_list_)
+ observer.WorkerVersionDoomed(host.get());
}
void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
@@ -156,7 +158,8 @@ void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
return;
scoped_refptr<WorkerDevToolsAgentHost> agent_host(it->second);
agent_host->WorkerDestroyed();
- FOR_EACH_OBSERVER(Observer, observer_list_, WorkerDestroyed(it->second));
+ for (auto& observer : observer_list_)
+ observer.WorkerDestroyed(it->second);
}
void ServiceWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id) {
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
index c5ea9be2fb2..921123022c4 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -27,6 +27,7 @@ SharedWorkerDevToolsAgentHost::SharedWorkerDevToolsAgentHost(
const SharedWorkerInstance& shared_worker)
: WorkerDevToolsAgentHost(worker_id),
shared_worker_(new SharedWorkerInstance(shared_worker)) {
+ NotifyCreated();
}
std::string SharedWorkerDevToolsAgentHost::GetType() {
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 c729ee5561e..b29fc85b034 100644
--- a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -98,7 +98,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
EXPECT_EQ(2U, list.size());
EXPECT_EQ(DevToolsAgentHost::kTypePage, list[0]->GetType());
EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec());
- EXPECT_EQ(DevToolsAgentHost::kTypePage, list[1]->GetType());
+ EXPECT_EQ(DevToolsAgentHost::kTypeFrame, list[1]->GetType());
EXPECT_EQ(cross_site_url.spec(), list[1]->GetURL().spec());
EXPECT_EQ(std::string(), list[0]->GetParentId());
EXPECT_EQ(list[0]->GetId(), list[1]->GetParentId());
diff --git a/chromium/content/browser/devtools/worker_devtools_agent_host.cc b/chromium/content/browser/devtools/worker_devtools_agent_host.cc
index a7515ad7b81..35276b80903 100644
--- a/chromium/content/browser/devtools/worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/worker_devtools_agent_host.cc
@@ -6,6 +6,7 @@
#include "base/guid.h"
#include "content/browser/devtools/devtools_protocol_handler.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/schema_handler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -22,11 +23,11 @@ void WorkerDevToolsAgentHost::Attach() {
state_ = WORKER_INSPECTED;
AttachToWorker();
}
- if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
- host->Send(
- new DevToolsAgentMsg_Attach(worker_id_.second, GetId(), session_id()));
+ if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
+ host->Send(new DevToolsAgentMsg_Attach(
+ worker_id_.second, GetId(), session()->session_id()));
+ }
OnAttachedStateChanged(true);
- DevToolsAgentHostImpl::NotifyCallbacks(this, true);
}
void WorkerDevToolsAgentHost::Detach() {
@@ -39,7 +40,6 @@ void WorkerDevToolsAgentHost::Detach() {
} else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
state_ = WORKER_UNINSPECTED;
}
- DevToolsAgentHostImpl::NotifyCallbacks(this, false);
}
bool WorkerDevToolsAgentHost::DispatchProtocolMessage(
@@ -49,13 +49,13 @@ bool WorkerDevToolsAgentHost::DispatchProtocolMessage(
int call_id;
std::string method;
- if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id,
- &method))
+ if (protocol_handler_->HandleOptionalMessage(session()->session_id(), message,
+ &call_id, &method))
return true;
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
host->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
- worker_id_.second, session_id(), call_id, method, message));
+ worker_id_.second, session()->session_id(), call_id, method, message));
}
return true;
}
@@ -88,7 +88,7 @@ void WorkerDevToolsAgentHost::WorkerReadyForInspection() {
AttachToWorker();
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
host->Send(new DevToolsAgentMsg_Reattach(
- worker_id_.second, GetId(), session_id(),
+ worker_id_.second, GetId(), session()->session_id(),
chunk_processor_.state_cookie()));
}
OnAttachedStateChanged(true);
diff --git a/chromium/content/browser/devtools/worker_devtools_agent_host.h b/chromium/content/browser/devtools/worker_devtools_agent_host.h
index a6d8f25affe..e5d39f49507 100644
--- a/chromium/content/browser/devtools/worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/worker_devtools_agent_host.h
@@ -15,7 +15,6 @@ namespace devtools { namespace schema { class SchemaHandler; }}
class BrowserContext;
class DevToolsProtocolHandler;
-class SharedWorkerInstance;
class WorkerDevToolsAgentHost : public DevToolsAgentHostImpl,
public IPC::Listener {
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 cd2cdbd4918..a42eda4be6a 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -30,8 +30,9 @@
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/session_storage_usage_info.h"
-#include "content/public/common/origin_util.h"
#include "storage/browser/quota/special_storage_policy.h"
+#include "url/gurl.h"
+#include "url/origin.h"
namespace content {
namespace {
@@ -201,27 +202,41 @@ void DOMStorageContextImpl::GetSessionStorageUsage(
}
}
-void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin) {
+void DOMStorageContextImpl::DeleteLocalStorageForPhysicalOrigin(
+ const GURL& origin_url) {
DCHECK(!is_shutdown_);
+ url::Origin origin(origin_url);
DOMStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
std::vector<GURL> origins;
local->GetOriginsWithAreas(&origins);
- // Suborigin storage should be deleted in tandem with the physical origin's
- // storage. https://w3c.github.io/webappsec-suborigins/
- for (auto origin_candidate : origins) {
+ // Suborigin at the physical origin of |origin_url| should have their storage
+ // deleted as well.
+ // https://w3c.github.io/webappsec-suborigins/
+ for (const auto& origin_candidate_url : origins) {
+ url::Origin origin_candidate(origin_candidate_url);
// |origin| is guaranteed to be deleted below, so don't delete it until
- // then.
- if (origin_candidate == origin ||
- StripSuboriginFromUrl(origin_candidate) != origin) {
- continue;
+ // then. That is, only suborigins at the same physical origin as |origin|
+ // should be deleted at this point.
+ if (!origin_candidate.IsSameOriginWith(origin) &&
+ origin_candidate.IsSamePhysicalOriginWith(origin)) {
+ DeleteLocalStorage(origin_candidate_url);
}
- DeleteAndClearStorageNamespaceForOrigin(origin_candidate, local);
}
// It is important to always explicitly delete |origin|. If it does not appear
// it |origins| above, there still may be a directory open in the namespace in
// preparation for this storage, and this call will make sure that the
// directory is deleted.
- DeleteAndClearStorageNamespaceForOrigin(origin, local);
+ DeleteLocalStorage(origin_url);
+}
+
+void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin_url) {
+ DOMStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
+ local->DeleteLocalStorageOrigin(origin_url);
+ // Synthesize a 'cleared' event if the area is open so CachedAreas in
+ // renderers get emptied out too.
+ DOMStorageArea* area = local->GetOpenStorageArea(origin_url);
+ if (area)
+ NotifyAreaCleared(area, origin_url);
}
void DOMStorageContextImpl::DeleteSessionStorage(
@@ -301,9 +316,8 @@ void DOMStorageContextImpl::NotifyItemSet(
const base::string16& new_value,
const base::NullableString16& old_value,
const GURL& page_url) {
- FOR_EACH_OBSERVER(
- EventObserver, event_observers_,
- OnDOMStorageItemSet(area, key, new_value, old_value, page_url));
+ for (auto& observer : event_observers_)
+ observer.OnDOMStorageItemSet(area, key, new_value, old_value, page_url);
}
void DOMStorageContextImpl::NotifyItemRemoved(
@@ -311,17 +325,15 @@ void DOMStorageContextImpl::NotifyItemRemoved(
const base::string16& key,
const base::string16& old_value,
const GURL& page_url) {
- FOR_EACH_OBSERVER(
- EventObserver, event_observers_,
- OnDOMStorageItemRemoved(area, key, old_value, page_url));
+ for (auto& observer : event_observers_)
+ observer.OnDOMStorageItemRemoved(area, key, old_value, page_url);
}
void DOMStorageContextImpl::NotifyAreaCleared(
const DOMStorageArea* area,
const GURL& page_url) {
- FOR_EACH_OBSERVER(
- EventObserver, event_observers_,
- OnDOMStorageAreaCleared(area, page_url));
+ for (auto& observer : event_observers_)
+ observer.OnDOMStorageAreaCleared(area, page_url);
}
int64_t DOMStorageContextImpl::AllocateSessionId() {
@@ -623,15 +635,4 @@ void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
}
}
-void DOMStorageContextImpl::DeleteAndClearStorageNamespaceForOrigin(
- const GURL& origin,
- DOMStorageNamespace* local) {
- local->DeleteLocalStorageOrigin(origin);
- // Synthesize a 'cleared' event if the area is open so CachedAreas in
- // renderers get emptied out too.
- DOMStorageArea* area = local->GetOpenStorageArea(origin);
- if (area)
- NotifyAreaCleared(area, origin);
-}
-
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.h b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
index 0efcb9fd476..c8cf956796a 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
@@ -28,7 +28,6 @@
namespace base {
class FilePath;
class NullableString16;
-class Time;
}
namespace storage {
@@ -133,7 +132,8 @@ class CONTENT_EXPORT DOMStorageContextImpl
void GetLocalStorageUsage(std::vector<LocalStorageUsageInfo>* infos,
bool include_file_info);
void GetSessionStorageUsage(std::vector<SessionStorageUsageInfo>* infos);
- void DeleteLocalStorage(const GURL& origin);
+ void DeleteLocalStorageForPhysicalOrigin(const GURL& origin_url);
+ void DeleteLocalStorage(const GURL& origin_url);
void DeleteSessionStorage(const SessionStorageUsageInfo& usage_info);
// Used by content settings to alter the behavior around
@@ -223,9 +223,6 @@ class CONTENT_EXPORT DOMStorageContextImpl
void DeleteNextUnusedNamespace();
void DeleteNextUnusedNamespaceInCommitSequence();
- void DeleteAndClearStorageNamespaceForOrigin(const GURL& origin,
- DOMStorageNamespace* local);
-
// Collection of namespaces keyed by id.
StorageNamespaceMap namespaces_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
index 1b8aa99d5b2..0ad42f7538f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
@@ -20,6 +20,8 @@
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
using base::ASCIIToUTF16;
@@ -28,14 +30,15 @@ namespace content {
class DOMStorageContextImplTest : public testing::Test {
public:
DOMStorageContextImplTest()
- : kOrigin(GURL("http://dom_storage/")),
- kKey(ASCIIToUTF16("key")),
- kValue(ASCIIToUTF16("value")),
- kDontIncludeFileInfo(false),
- kDoIncludeFileInfo(true) {
- }
+ : kOrigin(GURL("http://dom_storage/")),
+ kSuborigin(GURL("http-so://foobar.dom_storage/")),
+ kKey(ASCIIToUTF16("key")),
+ kValue(ASCIIToUTF16("value")),
+ kDontIncludeFileInfo(false),
+ kDoIncludeFileInfo(true) {}
const GURL kOrigin;
+ const GURL kSuborigin;
const base::string16 kKey;
const base::string16 kValue;
const bool kDontIncludeFileInfo;
@@ -297,4 +300,95 @@ TEST_F(DOMStorageContextImplTest, PurgeMemory) {
EXPECT_EQ(0u, dom_namespace->GetUsageStatistics().total_cache_size);
}
+// Verifies that deleting the local storage for an origin will delete any
+// suborigins also present, and similarly, deleting a suborigin will delete the
+// physical origin as well.
+TEST_F(DOMStorageContextImplTest, DeleteSuboriginLocalStorage) {
+ context_->Shutdown();
+ context_ =
+ new DOMStorageContextImpl(temp_dir_.GetPath(), temp_dir_.GetPath(),
+ storage_policy_.get(), task_runner_.get());
+
+ DOMStorageNamespace* dom_namespace =
+ context_->GetStorageNamespace(kLocalStorageNamespaceId);
+ DOMStorageArea* origin_area = dom_namespace->OpenStorageArea(kOrigin);
+ DOMStorageArea* suborigin_area = dom_namespace->OpenStorageArea(kSuborigin);
+
+ const base::string16 kOriginKey(ASCIIToUTF16("foo"));
+ const base::string16 kOriginValue(ASCIIToUTF16("bar"));
+ const base::string16 kSuboriginKey(ASCIIToUTF16("foz"));
+ const base::string16 kSuboriginValue(ASCIIToUTF16("baz"));
+ base::NullableString16 old_nullable_value;
+
+ // Setup data for the first deletion (of the origin rather than the suborigin)
+ origin_area->SetItem(kOriginKey, kOriginValue, &old_nullable_value);
+ suborigin_area->SetItem(kSuboriginKey, kSuboriginValue, &old_nullable_value);
+
+ base::NullableString16 read_value;
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_EQ(kOriginValue, read_value.string());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_EQ(kSuboriginValue, read_value.string());
+
+ // Deleting the data for the physical origin should delete the data in the
+ // suborigin as well.
+ context_->DeleteLocalStorageForPhysicalOrigin(kOrigin);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_TRUE(read_value.is_null());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_TRUE(read_value.is_null());
+
+ // Setup data again for the second deletion (of the suborigin rather than the
+ // origin)
+ origin_area->SetItem(kOriginKey, kOriginValue, &old_nullable_value);
+ suborigin_area->SetItem(kSuboriginKey, kSuboriginValue, &old_nullable_value);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_EQ(kOriginValue, read_value.string());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_EQ(kSuboriginValue, read_value.string());
+
+ // Delete the suborigin by physical origin this time. This should delete both
+ // the suborigin and physical origin.
+ context_->DeleteLocalStorageForPhysicalOrigin(kSuborigin);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_TRUE(read_value.is_null());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_TRUE(read_value.is_null());
+
+ // Setup data again for the third deletion, to test deleting the storage one
+ // at a time.
+ origin_area->SetItem(kOriginKey, kOriginValue, &old_nullable_value);
+ suborigin_area->SetItem(kSuboriginKey, kSuboriginValue, &old_nullable_value);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_EQ(kOriginValue, read_value.string());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_EQ(kSuboriginValue, read_value.string());
+
+ // Delete the origin only. This should leave the suborigin.
+ context_->DeleteLocalStorage(kOrigin);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_TRUE(read_value.is_null());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_EQ(kSuboriginValue, read_value.string());
+
+ // Put the origin value back so suborigin deletion can be tested.
+ origin_area->SetItem(kOriginKey, kOriginValue, &old_nullable_value);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_EQ(kOriginValue, read_value.string());
+
+ // Delete the suborigin only. This should leave the origin.
+ context_->DeleteLocalStorage(kSuborigin);
+
+ read_value = origin_area->GetItem(kOriginKey);
+ EXPECT_EQ(kOriginValue, read_value.string());
+ read_value = suborigin_area->GetItem(kSuboriginKey);
+ EXPECT_TRUE(read_value.is_null());
+}
+
} // namespace content
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 528f713c79b..67353fd7b87 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -30,10 +30,10 @@
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_features.h"
#include "mojo/common/common_type_converters.h"
-#include "services/file/public/cpp/constants.h"
+#include "services/file/public/interfaces/constants.mojom.h"
#include "services/file/public/interfaces/file_system.mojom.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/connection.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
namespace {
@@ -83,7 +83,8 @@ void GetSessionStorageUsageHelper(
// for now).
class DOMStorageContextWrapper::MojoState {
public:
- MojoState(shell::Connector* connector, const base::FilePath& subdirectory)
+ MojoState(service_manager::Connector* connector,
+ const base::FilePath& subdirectory)
: connector_(connector),
// TODO(michaeln): Enable writing to disk when db is versioned,
// for now using an empty subdirectory to use an in-memory db.
@@ -102,7 +103,7 @@ class DOMStorageContextWrapper::MojoState {
}
void OnUserServiceConnectionComplete() {
- CHECK_EQ(shell::mojom::ConnectResult::SUCCEEDED,
+ CHECK_EQ(service_manager::mojom::ConnectResult::SUCCEEDED,
file_service_connection_->GetResult());
}
@@ -123,7 +124,7 @@ class DOMStorageContextWrapper::MojoState {
// Maps between an origin and its prefixed LevelDB view.
std::map<url::Origin, std::unique_ptr<LevelDBWrapperImpl>> level_db_wrappers_;
- shell::Connector* const connector_;
+ service_manager::Connector* const connector_;
const base::FilePath subdirectory_;
enum ConnectionState {
@@ -132,7 +133,7 @@ class DOMStorageContextWrapper::MojoState {
CONNECTION_FINISHED
} connection_state_;
- std::unique_ptr<shell::Connection> file_service_connection_;
+ std::unique_ptr<service_manager::Connection> file_service_connection_;
file::mojom::FileSystemPtr file_system_;
filesystem::mojom::DirectoryPtr directory_;
@@ -153,7 +154,7 @@ void DOMStorageContextWrapper::MojoState::OpenLocalStorage(
if (connection_state_ == NO_CONNECTION) {
CHECK(connector_);
file_service_connection_ =
- connector_->Connect(file::kFileServiceName);
+ connector_->Connect(file::mojom::kServiceName);
connection_state_ = CONNECTION_IN_PROGRESS;
file_service_connection_->AddConnectionCompletedClosure(
base::Bind(&MojoState::OnUserServiceConnectionComplete,
@@ -166,11 +167,10 @@ void DOMStorageContextWrapper::MojoState::OpenLocalStorage(
// We were given a subdirectory to write to. Get it and use a disk backed
// database.
file_service_connection_->GetInterface(&file_system_);
- file_system_->GetSubDirectory(
- mojo::String::From(subdirectory_.AsUTF8Unsafe()),
- GetProxy(&directory_),
- base::Bind(&MojoState::OnDirectoryOpened,
- weak_ptr_factory_.GetWeakPtr()));
+ file_system_->GetSubDirectory(subdirectory_.AsUTF8Unsafe(),
+ GetProxy(&directory_),
+ base::Bind(&MojoState::OnDirectoryOpened,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
// We were not given a subdirectory. Use a memory backed database.
file_service_connection_->GetInterface(&leveldb_service_);
@@ -262,7 +262,7 @@ void DOMStorageContextWrapper::MojoState::BindLocalStorage(
}
DOMStorageContextWrapper::DOMStorageContextWrapper(
- shell::Connector* connector,
+ service_manager::Connector* connector,
const base::FilePath& profile_path,
const base::FilePath& local_partition_path,
storage::SpecialStoragePolicy* special_storage_policy) {
@@ -317,6 +317,15 @@ void DOMStorageContextWrapper::GetSessionStorageUsage(
base::RetainedRef(context_), callback));
}
+void DOMStorageContextWrapper::DeleteLocalStorageForPhysicalOrigin(
+ const GURL& origin) {
+ DCHECK(context_.get());
+ context_->task_runner()->PostShutdownBlockingTask(
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::Bind(&DOMStorageContextImpl::DeleteLocalStorageForPhysicalOrigin,
+ context_, origin));
+}
+
void DOMStorageContextWrapper::DeleteLocalStorage(const GURL& origin) {
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
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 d58bdf2743f..d8e30310edc 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -22,7 +22,7 @@ namespace base {
class FilePath;
}
-namespace shell {
+namespace service_manager {
class Connector;
}
@@ -33,7 +33,6 @@ class SpecialStoragePolicy;
namespace content {
class DOMStorageContextImpl;
-class LevelDBWrapperImpl;
// This is owned by Storage Partition and encapsulates all its dom storage
// state.
@@ -44,7 +43,7 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
public:
// If |data_path| is empty, nothing will be saved to disk.
DOMStorageContextWrapper(
- shell::Connector* connector,
+ service_manager::Connector* connector,
const base::FilePath& data_path,
const base::FilePath& local_partition_path,
storage::SpecialStoragePolicy* special_storage_policy);
@@ -54,6 +53,7 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
const GetLocalStorageUsageCallback& callback) override;
void GetSessionStorageUsage(
const GetSessionStorageUsageCallback& callback) override;
+ void DeleteLocalStorageForPhysicalOrigin(const GURL& origin) override;
void DeleteLocalStorage(const GURL& origin) override;
void DeleteSessionStorage(const SessionStorageUsageInfo& usage_info) override;
void SetSaveSessionStorageOnDisk() override;
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.cc b/chromium/content/browser/dom_storage/dom_storage_database.cc
index 5b1b5bd63c3..d11aad76540 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database.cc
@@ -158,9 +158,8 @@ bool DOMStorageDatabase::LazyOpen(bool create_if_needed) {
db_.reset(new sql::Connection());
db_->set_histogram_tag("DOMStorageDatabase");
- // TODO(shess): The current mitigation for http://crbug.com/537742 stores
- // state in the meta table, which this database does not use.
- db_->set_mmap_disabled();
+ // This db does not use [meta] table, store mmap status data elsewhere.
+ db_->set_mmap_alt_status();
if (file_path_.empty()) {
// This code path should only be triggered by unit tests.
diff --git a/chromium/content/browser/download/base_file.h b/chromium/content/browser/download/base_file.h
index b247057e44c..8351c49be34 100644
--- a/chromium/content/browser/download/base_file.h
+++ b/chromium/content/browser/download/base_file.h
@@ -16,7 +16,6 @@
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/download_interrupt_reasons.h"
diff --git a/chromium/content/browser/download/base_file_unittest.cc b/chromium/content/browser/download/base_file_unittest.cc
index b5e21d6ab79..6b07d8d1315 100644
--- a/chromium/content/browser/download/base_file_unittest.cc
+++ b/chromium/content/browser/download/base_file_unittest.cc
@@ -13,12 +13,11 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/test_file_util.h"
#include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/download_interrupt_reasons.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -56,9 +55,7 @@ class BaseFileTest : public testing::Test {
BaseFileTest()
: expect_file_survives_(false),
expect_in_progress_(true),
- expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE),
- file_thread_(BrowserThread::FILE, &message_loop_) {
- }
+ expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
@@ -199,9 +196,7 @@ class BaseFileTest : public testing::Test {
std::string expected_data_;
DownloadInterruptReason expected_error_;
- // Mock file thread to satisfy debug checks in BaseFile.
- base::MessageLoop message_loop_;
- BrowserThreadImpl file_thread_;
+ TestBrowserThreadBundle thread_bundle_;
};
// This will initialize the entire array to zero.
diff --git a/chromium/content/browser/download/download_file.h b/chromium/content/browser/download/download_file.h
index c30cab9fe30..0e34ab24362 100644
--- a/chromium/content/browser/download/download_file.h
+++ b/chromium/content/browser/download/download_file.h
@@ -18,8 +18,6 @@ class GURL;
namespace content {
-class DownloadManager;
-
// 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
diff --git a/chromium/content/browser/download/download_file_factory.h b/chromium/content/browser/download/download_file_factory.h
index afb921d7025..f940377d78e 100644
--- a/chromium/content/browser/download/download_file_factory.h
+++ b/chromium/content/browser/download/download_file_factory.h
@@ -14,10 +14,6 @@
#include "content/common/content_export.h"
#include "url/gurl.h"
-namespace crypto {
-class SecureHash;
-}
-
namespace net {
class NetLogWithSource;
}
@@ -27,7 +23,6 @@ namespace content {
class ByteStreamReader;
class DownloadDestinationObserver;
class DownloadFile;
-class DownloadManager;
struct DownloadSaveInfo;
class CONTENT_EXPORT DownloadFileFactory {
diff --git a/chromium/content/browser/download/download_file_impl.h b/chromium/content/browser/download/download_file_impl.h
index 43cfcf43d41..9a275190aa5 100644
--- a/chromium/content/browser/download/download_file_impl.h
+++ b/chromium/content/browser/download/download_file_impl.h
@@ -28,8 +28,6 @@
namespace content {
class ByteStreamReader;
class DownloadDestinationObserver;
-class DownloadManager;
-struct DownloadCreateInfo;
class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
public:
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index 2ee86811bcf..d4e9ddc9cb1 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -17,7 +17,6 @@
#include "base/test/test_file_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_destination_observer.h"
@@ -26,6 +25,7 @@
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_manager.h"
#include "content/public/test/mock_download_manager.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/file_stream.h"
#include "net/base/mock_file_stream.h"
#include "net/base/net_errors.h"
@@ -138,15 +138,12 @@ class DownloadFileTest : public testing::Test {
static const int kDummyChildId;
static const int kDummyRequestId;
- DownloadFileTest() :
- observer_(new StrictMock<MockDownloadDestinationObserver>),
- observer_factory_(observer_.get()),
- input_stream_(NULL),
- bytes_(-1),
- bytes_per_sec_(-1),
- ui_thread_(BrowserThread::UI, &loop_),
- file_thread_(BrowserThread::FILE, &loop_) {
- }
+ DownloadFileTest()
+ : observer_(new StrictMock<MockDownloadDestinationObserver>),
+ observer_factory_(observer_.get()),
+ input_stream_(NULL),
+ bytes_(-1),
+ bytes_per_sec_(-1) {}
~DownloadFileTest() override {}
@@ -372,8 +369,6 @@ class DownloadFileTest : public testing::Test {
int64_t bytes_;
int64_t bytes_per_sec_;
- base::MessageLoop loop_;
-
private:
void SetRenameResult(const base::Closure& closure,
DownloadInterruptReason* reason_p,
@@ -387,10 +382,7 @@ class DownloadFileTest : public testing::Test {
closure.Run();
}
- // UI thread.
- BrowserThreadImpl ui_thread_;
- // File thread to satisfy debug checks in DownloadFile.
- BrowserThreadImpl file_thread_;
+ TestBrowserThreadBundle thread_bundle_;
// Keep track of what data should be saved to the disk file.
std::string expected_data_;
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index 99baf7e8c20..9f9eae57ca6 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -93,6 +93,21 @@ static base::FilePath DownloadFileDetach(
return full_path;
}
+static base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ base::FilePath temp_file_path;
+ if (base::CreateTemporaryFile(&temp_file_path) &&
+ base::CopyFile(download_file->FullPath(), temp_file_path)) {
+ return temp_file_path;
+ } else {
+ // Deletes the file at |temp_file_path|.
+ if (!base::DirectoryExists(temp_file_path))
+ base::DeleteFile(temp_file_path, false);
+ temp_file_path.clear();
+ return base::FilePath();
+ }
+}
+
static void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
download_file->Cancel();
@@ -246,7 +261,8 @@ DownloadItemImpl::~DownloadItemImpl() {
// DownloadManager shutdown.
DCHECK(!download_file_.get());
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this));
+ for (auto& observer : observers_)
+ observer.OnDownloadDestroyed(this);
delegate_->AssertStateConsistent(this);
delegate_->Detach();
}
@@ -267,7 +283,8 @@ void DownloadItemImpl::UpdateObservers() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DVLOG(20) << __func__ << "()";
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
+ for (auto& observer : observers_)
+ observer.OnDownloadUpdated(this);
}
void DownloadItemImpl::ValidateDangerousDownload() {
@@ -297,23 +314,32 @@ void DownloadItemImpl::ValidateDangerousDownload() {
}
void DownloadItemImpl::StealDangerousDownload(
+ bool delete_file_afterward,
const AcquireFileCallback& callback) {
DVLOG(20) << __func__ << "() download = " << DebugString(true);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(IsDangerous());
+ DCHECK(AllDataSaved());
- if (download_file_) {
+ if (delete_file_afterward) {
+ if (download_file_) {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DownloadFileDetach, base::Passed(&download_file_)),
+ callback);
+ } else {
+ callback.Run(current_path_);
+ }
+ current_path_.clear();
+ Remove();
+ // Download item has now been deleted.
+ } else if (download_file_) {
BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&DownloadFileDetach, base::Passed(&download_file_)),
- callback);
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&MakeCopyOfDownloadFile, download_file_.get()), callback);
} else {
callback.Run(current_path_);
}
- current_path_.clear();
- Remove();
- // We have now been deleted.
}
void DownloadItemImpl::Pause() {
@@ -428,7 +454,8 @@ void DownloadItemImpl::OpenDownload() {
delegate_->CheckForFileRemoval(this);
RecordOpen(GetEndTime(), !GetOpened());
opened_ = true;
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
+ for (auto& observer : observers_)
+ observer.OnDownloadOpened(this);
delegate_->OpenDownload(this);
}
@@ -974,7 +1001,8 @@ void DownloadItemImpl::UpdateValidatorsOnResumption(
}
void DownloadItemImpl::NotifyRemoved() {
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
+ for (auto& observer : observers_)
+ observer.OnDownloadRemoved(this);
}
void DownloadItemImpl::OnDownloadedFileRemoved() {
@@ -1371,7 +1399,6 @@ void DownloadItemImpl::MaybeCompleteDownload() {
base::Bind(&DownloadItemImpl::MaybeCompleteDownload,
weak_ptr_factory_.GetWeakPtr())))
return;
-
// Confirm we're in the proper set of states to be here; have all data, have a
// history handle, (validated or safe).
DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index a66201a404c..c899f25016b 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -101,7 +101,8 @@ class CONTENT_EXPORT DownloadItemImpl
void RemoveObserver(DownloadItem::Observer* observer) override;
void UpdateObservers() override;
void ValidateDangerousDownload() override;
- void StealDangerousDownload(const AcquireFileCallback& callback) override;
+ void StealDangerousDownload(bool need_removal,
+ const AcquireFileCallback& callback) override;
void Pause() override;
void Resume() override;
void Cancel(bool user_cancel) override;
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index 8d3093ac369..23002f0af4e 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -7,14 +7,16 @@
#include <stdint.h>
#include <iterator>
+#include <map>
+#include <memory>
#include <queue>
#include <utility>
#include "base/callback.h"
#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
@@ -254,7 +256,6 @@ class DownloadItemTest : public testing::Test {
~DownloadItemTest() {
RunAllPendingInMessageLoops();
- base::STLDeleteElements(&allocated_downloads_);
}
DownloadItemImpl* CreateDownloadItemWithCreateInfo(
@@ -262,7 +263,7 @@ class DownloadItemTest : public testing::Test {
DownloadItemImpl* download =
new DownloadItemImpl(&delegate_, next_download_id_++, *(info.get()),
net::NetLogWithSource());
- allocated_downloads_.insert(download);
+ allocated_downloads_[download] = base::WrapUnique(download);
return download;
}
@@ -274,7 +275,7 @@ class DownloadItemTest : public testing::Test {
DownloadItemImpl* download =
new DownloadItemImpl(&delegate_, create_info_->download_id,
*create_info_, net::NetLogWithSource());
- allocated_downloads_.insert(download);
+ allocated_downloads_[download] = base::WrapUnique(download);
return download;
}
@@ -376,7 +377,6 @@ class DownloadItemTest : public testing::Test {
// Destroy a previously created download item.
void DestroyDownloadItem(DownloadItem* item) {
allocated_downloads_.erase(item);
- delete item;
}
void RunAllPendingInMessageLoops() { base::RunLoop().RunUntilIdle(); }
@@ -397,7 +397,7 @@ class DownloadItemTest : public testing::Test {
private:
TestBrowserThreadBundle thread_bundle_;
StrictMock<MockDelegate> delegate_;
- std::set<DownloadItem*> allocated_downloads_;
+ std::map<DownloadItem*, std::unique_ptr<DownloadItem>> allocated_downloads_;
std::unique_ptr<DownloadCreateInfo> create_info_;
uint32_t next_download_id_ = DownloadItem::kInvalidId + 1;
TestBrowserContext browser_context_;
@@ -486,6 +486,125 @@ TEST_F(DownloadItemTest, NotificationAfterDestroyed) {
ASSERT_TRUE(observer.download_destroyed());
}
+TEST_F(DownloadItemTest, NotificationAfterRemove) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ MockDownloadFile* download_file =
+ CallDownloadItemStart(item, &target_callback);
+ EXPECT_CALL(*download_file, Cancel());
+ EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
+ TestDownloadItemObserver observer(item);
+
+ item->Remove();
+ ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
+ ASSERT_TRUE(observer.download_removed());
+}
+
+TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
+ // Setting to NOT_DANGEROUS does not trigger a notification.
+ DownloadItemImpl* safe_item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(safe_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ TestDownloadItemObserver safe_observer(safe_item);
+
+ safe_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
+ EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
+ safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(safe_item, download_file, DownloadItem::IN_PROGRESS);
+
+ // Setting to unsafe url or unsafe file should trigger a notification.
+ DownloadItemImpl* unsafeurl_item = CreateDownloadItem();
+ download_file =
+ DoIntermediateRename(unsafeurl_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ TestDownloadItemObserver unsafeurl_observer(unsafeurl_item);
+
+ unsafeurl_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
+ EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
+ unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
+ EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
+
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
+ unsafeurl_item->ValidateDangerousDownload();
+ EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(unsafeurl_item, download_file, DownloadItem::IN_PROGRESS);
+
+ DownloadItemImpl* unsafefile_item = CreateDownloadItem();
+ download_file =
+ DoIntermediateRename(unsafefile_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ TestDownloadItemObserver unsafefile_observer(unsafefile_item);
+
+ unsafefile_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
+ EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
+ unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
+ EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
+
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
+ unsafefile_item->ValidateDangerousDownload();
+ EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(unsafefile_item, download_file, DownloadItem::IN_PROGRESS);
+}
+
+// DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
+// DownloadFile::Rename(). Once the rename
+// completes, DownloadItemImpl receives a notification with the new file
+// name. Check that observers are updated when the new filename is available and
+// not before.
+TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ DownloadItemImplDelegate::DownloadTargetCallback callback;
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
+ TestDownloadItemObserver observer(item);
+ base::FilePath target_path(kDummyTargetPath);
+ base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
+ base::FilePath new_intermediate_path(
+ target_path.InsertBeforeExtensionASCII("y"));
+ EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
+
+ // Currently, a notification would be generated if the danger type is anything
+ // other than NOT_DANGEROUS.
+ callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
+ EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
+ RunAllPendingInMessageLoops();
+ EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
+ EXPECT_EQ(new_intermediate_path, item->GetFullPath());
+
+ CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
+}
+
+TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ TestDownloadItemObserver observer(item);
+ MockDownloadFile* mock_download_file(new MockDownloadFile);
+ std::unique_ptr<DownloadFile> download_file(mock_download_file);
+ std::unique_ptr<DownloadRequestHandleInterface> request_handle(
+ new NiceMock<MockRequestHandle>);
+
+ EXPECT_CALL(*mock_download_file, Initialize(_));
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
+ item->Start(std::move(download_file), std::move(request_handle),
+ *create_info());
+
+ item->Pause();
+ ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
+
+ ASSERT_TRUE(item->IsPaused());
+
+ item->Resume();
+ ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
+
+ RunAllPendingInMessageLoops();
+
+ CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
+}
+
// Test that a download is resumed automatcially after a continuable interrupt.
TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
DownloadItemImpl* item = CreateDownloadItem();
@@ -728,127 +847,6 @@ TEST_F(DownloadItemTest, ResumeUsingFinalURL) {
CleanupItem(item, nullptr, DownloadItem::IN_PROGRESS);
}
-TEST_F(DownloadItemTest, NotificationAfterRemove) {
- DownloadItemImpl* item = CreateDownloadItem();
- DownloadItemImplDelegate::DownloadTargetCallback target_callback;
- MockDownloadFile* download_file =
- CallDownloadItemStart(item, &target_callback);
- EXPECT_CALL(*download_file, Cancel());
- EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
- TestDownloadItemObserver observer(item);
-
- item->Remove();
- ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
- ASSERT_TRUE(observer.download_removed());
-}
-
-TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
- // Setting to NOT_DANGEROUS does not trigger a notification.
- DownloadItemImpl* safe_item = CreateDownloadItem();
- MockDownloadFile* download_file =
- DoIntermediateRename(safe_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
- TestDownloadItemObserver safe_observer(safe_item);
-
- safe_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
- EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
- safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
- EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
- CleanupItem(safe_item, download_file, DownloadItem::IN_PROGRESS);
-
- // Setting to unsafe url or unsafe file should trigger a notification.
- DownloadItemImpl* unsafeurl_item =
- CreateDownloadItem();
- download_file =
- DoIntermediateRename(unsafeurl_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
- TestDownloadItemObserver unsafeurl_observer(unsafeurl_item);
-
- unsafeurl_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
- EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
- unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
- EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
-
- EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
- .WillOnce(Return(true));
- EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
- unsafeurl_item->ValidateDangerousDownload();
- EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
- CleanupItem(unsafeurl_item, download_file, DownloadItem::IN_PROGRESS);
-
- DownloadItemImpl* unsafefile_item =
- CreateDownloadItem();
- download_file =
- DoIntermediateRename(unsafefile_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
- TestDownloadItemObserver unsafefile_observer(unsafefile_item);
-
- unsafefile_item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
- EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
- unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
- EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
-
- EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
- .WillOnce(Return(true));
- EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
- unsafefile_item->ValidateDangerousDownload();
- EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
- CleanupItem(unsafefile_item, download_file, DownloadItem::IN_PROGRESS);
-}
-
-// DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
-// DownloadFile::Rename(). Once the rename
-// completes, DownloadItemImpl receives a notification with the new file
-// name. Check that observers are updated when the new filename is available and
-// not before.
-TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
- DownloadItemImpl* item = CreateDownloadItem();
- DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
- TestDownloadItemObserver observer(item);
- base::FilePath target_path(kDummyTargetPath);
- base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
- base::FilePath new_intermediate_path(
- target_path.InsertBeforeExtensionASCII("y"));
- EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameAndUniquifyCallback(
- DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
-
- // Currently, a notification would be generated if the danger type is anything
- // other than NOT_DANGEROUS.
- callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
- DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
- EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
- RunAllPendingInMessageLoops();
- EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
- EXPECT_EQ(new_intermediate_path, item->GetFullPath());
-
- CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
-}
-
-TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
- DownloadItemImpl* item = CreateDownloadItem();
- TestDownloadItemObserver observer(item);
- MockDownloadFile* mock_download_file(new MockDownloadFile);
- std::unique_ptr<DownloadFile> download_file(mock_download_file);
- std::unique_ptr<DownloadRequestHandleInterface> request_handle(
- new NiceMock<MockRequestHandle>);
-
- EXPECT_CALL(*mock_download_file, Initialize(_));
- EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
- item->Start(std::move(download_file), std::move(request_handle),
- *create_info());
-
- item->Pause();
- ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
-
- ASSERT_TRUE(item->IsPaused());
-
- item->Resume();
- ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
-
- RunAllPendingInMessageLoops();
-
- CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
-}
-
TEST_F(DownloadItemTest, DisplayName) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
@@ -1541,7 +1539,7 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
}
-TEST_F(DownloadItemTest, StealDangerousDownload) {
+TEST_F(DownloadItemTest, StealDangerousDownloadAndDiscard) {
DownloadItemImpl* item = CreateDownloadItem();
MockDownloadFile* download_file =
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
@@ -1553,7 +1551,9 @@ TEST_F(DownloadItemTest, StealDangerousDownload) {
EXPECT_CALL(*download_file, Detach());
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
+ item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
item->StealDangerousDownload(
+ true, // delete_file_after_feedback
base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
weak_ptr_factory.GetWeakPtr(),
base::Unretained(&returned_path)));
@@ -1561,6 +1561,26 @@ TEST_F(DownloadItemTest, StealDangerousDownload) {
EXPECT_EQ(full_path, returned_path);
}
+TEST_F(DownloadItemTest, StealDangerousDownloadAndKeep) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
+ ASSERT_TRUE(item->IsDangerous());
+ base::FilePath full_path(FILE_PATH_LITERAL("foo.txt"));
+ base::FilePath returned_path;
+ EXPECT_CALL(*download_file, FullPath()).WillOnce(ReturnRefOfCopy(full_path));
+ base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
+ item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
+ item->StealDangerousDownload(
+ false, // delete_file_after_feedback
+ base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
+ weak_ptr_factory.GetWeakPtr(),
+ base::Unretained(&returned_path)));
+ RunAllPendingInMessageLoops();
+ EXPECT_NE(full_path, returned_path);
+ CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
+}
+
TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
base::FilePath returned_path;
DownloadItemImpl* item = CreateDownloadItem();
@@ -1577,10 +1597,11 @@ TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
+ item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
item->StealDangerousDownload(
- base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
- weak_ptr_factory.GetWeakPtr(),
- base::Unretained(&returned_path)));
+ true, base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
+ weak_ptr_factory.GetWeakPtr(),
+ base::Unretained(&returned_path)));
RunAllPendingInMessageLoops();
EXPECT_EQ(full_path, returned_path);
}
@@ -1598,10 +1619,11 @@ TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
+ item->OnAllDataSaved(0, std::unique_ptr<crypto::SecureHash>());
item->StealDangerousDownload(
- base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
- weak_ptr_factory.GetWeakPtr(),
- base::Unretained(&returned_path)));
+ true, base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
+ weak_ptr_factory.GetWeakPtr(),
+ base::Unretained(&returned_path)));
RunAllPendingInMessageLoops();
EXPECT_TRUE(returned_path.empty());
}
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 176ec387ecf..8131d2740b1 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -172,14 +172,13 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
} // namespace
-DownloadManagerImpl::DownloadManagerImpl(
- net::NetLog* net_log,
- BrowserContext* browser_context)
+DownloadManagerImpl::DownloadManagerImpl(net::NetLog* net_log,
+ BrowserContext* browser_context)
: item_factory_(new DownloadItemFactoryImpl()),
file_factory_(new DownloadFileFactory()),
shutdown_needed_(true),
browser_context_(browser_context),
- delegate_(NULL),
+ delegate_(nullptr),
net_log_(net_log),
weak_factory_(this) {
DCHECK(browser_context);
@@ -198,7 +197,7 @@ DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
net::NetLogWithSource::Make(net_log_, net::NetLogSourceType::DOWNLOAD);
DownloadItemImpl* download =
item_factory_->CreateActiveItem(this, id, info, net_log);
- downloads_[id] = download;
+ downloads_[id] = base::WrapUnique(download);
downloads_by_guid_[download->GetGuid()] = download;
return download;
}
@@ -274,7 +273,8 @@ void DownloadManagerImpl::Shutdown() {
return;
shutdown_needed_ = false;
- FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown(this));
+ for (auto& observer : observers_)
+ observer.ManagerGoingDown(this);
// TODO(benjhayden): Consider clearing observers_.
// If there are in-progress downloads, cancel them. This also goes for
@@ -282,11 +282,11 @@ void DownloadManagerImpl::Shutdown() {
// accepted or discarded. Canceling will remove the intermediate download
// file.
for (const auto& it : downloads_) {
- DownloadItemImpl* download = it.second;
+ DownloadItemImpl* download = it.second.get();
if (download->GetState() == DownloadItem::IN_PROGRESS)
download->Cancel(false);
}
- base::STLDeleteValues(&downloads_);
+ downloads_.clear();
downloads_by_guid_.clear();
url_downloaders_.clear();
@@ -295,7 +295,7 @@ void DownloadManagerImpl::Shutdown() {
if (delegate_)
delegate_->Shutdown();
- delegate_ = NULL;
+ delegate_ = nullptr;
}
void DownloadManagerImpl::StartDownload(
@@ -331,11 +331,11 @@ void DownloadManagerImpl::StartDownloadWithId(
uint32_t id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_NE(content::DownloadItem::kInvalidId, id);
- DownloadItemImpl* download = NULL;
+ DownloadItemImpl* download = nullptr;
if (new_download) {
download = CreateActiveItem(id, *info);
} else {
- DownloadMap::iterator item_iterator = downloads_.find(id);
+ auto item_iterator = downloads_.find(id);
// Trying to resume an interrupted download.
if (item_iterator == downloads_.end() ||
(item_iterator->second->GetState() == DownloadItem::CANCELLED)) {
@@ -344,14 +344,14 @@ void DownloadManagerImpl::StartDownloadWithId(
// while resuming, then also ignore the request.
info->request_handle->CancelRequest();
if (!on_started.is_null())
- on_started.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+ on_started.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
// The ByteStreamReader lives and dies on the FILE thread.
if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
stream.release());
return;
}
- download = item_iterator->second;
+ download = item_iterator->second.get();
}
base::FilePath default_download_directory;
@@ -383,8 +383,10 @@ void DownloadManagerImpl::StartDownloadWithId(
// For new downloads, we notify here, rather than earlier, so that
// the download_file is bound to download and all the usual
// setters (e.g. Cancel) work.
- if (new_download)
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
+ if (new_download) {
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, download);
+ }
if (!on_started.is_null())
on_started.Run(download, DOWNLOAD_INTERRUPT_REASON_NONE);
@@ -393,7 +395,7 @@ void DownloadManagerImpl::StartDownloadWithId(
void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (const auto& it : downloads_) {
- DownloadItemImpl* item = it.second;
+ DownloadItemImpl* item = it.second.get();
CheckForFileRemoval(item);
}
}
@@ -457,19 +459,19 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
DownloadItemImpl* download_item = item_factory_->CreateSavePageItem(
this, id, main_file_path, page_url, mime_type, std::move(request_handle),
net_log);
- downloads_[download_item->GetId()] = download_item;
+ downloads_[download_item->GetId()] = base::WrapUnique(download_item);
DCHECK(!base::ContainsKey(downloads_by_guid_, download_item->GetGuid()));
downloads_by_guid_[download_item->GetGuid()] = download_item;
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
- this, download_item));
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, download_item);
if (!item_created.is_null())
item_created.Run(download_item);
}
void DownloadManagerImpl::OnSavePackageSuccessfullyFinished(
DownloadItem* download_item) {
- FOR_EACH_OBSERVER(Observer, observers_,
- OnSavePackageSuccessfullyFinished(this, download_item));
+ for (auto& observer : observers_)
+ observer.OnSavePackageSuccessfullyFinished(this, download_item);
}
// Resume a download of a specific URL. We send the request to the
@@ -506,11 +508,7 @@ void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
return;
downloads_by_guid_.erase(download->GetGuid());
-
- uint32_t download_id = download->GetId();
- if (downloads_.erase(download_id) == 0)
- return;
- delete download;
+ downloads_.erase(download->GetId());
}
void DownloadManagerImpl::AddUrlDownloader(
@@ -610,9 +608,9 @@ bool RemoveDownloadByURLAndTime(
int DownloadManagerImpl::RemoveDownloads(const DownloadRemover& remover) {
int count = 0;
- DownloadMap::const_iterator it = downloads_.begin();
+ auto it = downloads_.begin();
while (it != downloads_.end()) {
- DownloadItemImpl* download = it->second;
+ DownloadItemImpl* download = it->second.get();
// Increment done here to protect against invalidation below.
++it;
@@ -694,7 +692,7 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
bool opened) {
if (base::ContainsKey(downloads_, id)) {
NOTREACHED();
- return NULL;
+ return nullptr;
}
DCHECK(!base::ContainsKey(downloads_by_guid_, guid));
DownloadItemImpl* item = item_factory_->CreatePersistedItem(
@@ -703,9 +701,10 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
start_time, end_time, etag, last_modified, received_bytes, total_bytes,
hash, state, danger_type, interrupt_reason, opened,
net::NetLogWithSource::Make(net_log_, net::NetLogSourceType::DOWNLOAD));
- downloads_[id] = item;
+ downloads_[id] = base::WrapUnique(item);
downloads_by_guid_[guid] = item;
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item));
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, item);
DVLOG(20) << __func__ << "() download = " << item->DebugString(true);
return item;
}
@@ -735,8 +734,9 @@ int DownloadManagerImpl::NonMaliciousInProgressCount() const {
}
DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
- return base::ContainsKey(downloads_, download_id) ? downloads_[download_id]
- : nullptr;
+ return base::ContainsKey(downloads_, download_id)
+ ? downloads_[download_id].get()
+ : nullptr;
}
DownloadItem* DownloadManagerImpl::GetDownloadByGuid(const std::string& guid) {
@@ -747,14 +747,14 @@ DownloadItem* DownloadManagerImpl::GetDownloadByGuid(const std::string& guid) {
void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) {
for (const auto& it : downloads_) {
- downloads->push_back(it.second);
+ downloads->push_back(it.second.get());
}
}
void DownloadManagerImpl::OpenDownload(DownloadItemImpl* download) {
int num_unopened = 0;
for (const auto& it : downloads_) {
- DownloadItemImpl* item = it.second;
+ DownloadItemImpl* item = it.second.get();
if ((item->GetState() == DownloadItem::COMPLETE) &&
!item->GetOpened())
++num_unopened;
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index f9dfc8bd1ab..e21dc123a3f 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -138,7 +138,6 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
private:
using DownloadSet = std::set<DownloadItem*>;
- using DownloadMap = std::unordered_map<uint32_t, DownloadItemImpl*>;
using DownloadGuidMap = std::unordered_map<std::string, DownloadItemImpl*>;
using DownloadItemImplVector = std::vector<DownloadItemImpl*>;
using DownloadRemover = base::Callback<bool(const DownloadItemImpl*)>;
@@ -213,7 +212,7 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
// "save page as" downloads.
// TODO(asanka): Remove this container in favor of downloads_by_guid_ as a
// part of http://crbug.com/593020.
- DownloadMap downloads_;
+ std::unordered_map<uint32_t, std::unique_ptr<DownloadItemImpl>> downloads_;
// Same as the above, but maps from GUID to download item. Note that the
// container is case sensitive. Hence the key needs to be normalized to
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 1c56e0c0f2d..70a0d1322e8 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -117,7 +117,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_METHOD0(OpenDownload, void());
MOCK_METHOD0(ShowDownloadInShell, void());
MOCK_METHOD0(ValidateDangerousDownload, void());
- MOCK_METHOD1(StealDangerousDownload, void(const AcquireFileCallback&));
+ MOCK_METHOD2(StealDangerousDownload, void(bool, const AcquireFileCallback&));
MOCK_METHOD3(UpdateProgress, void(int64_t, int64_t, const std::string&));
MOCK_METHOD1(Cancel, void(bool));
MOCK_METHOD0(MarkAsComplete, void());
@@ -767,7 +767,8 @@ TEST_F(DownloadManagerTest, GetDownloadByGuid) {
namespace {
base::Callback<bool(const GURL&)> GetSingleURLFilter(const GURL& url) {
- return base::Bind(&GURL::operator==, base::Owned(new GURL(url)));
+ return base::Bind(static_cast<bool (*)(const GURL&, const GURL&)>(operator==),
+ GURL(url));
}
} // namespace
diff --git a/chromium/content/browser/download/download_net_log_parameters.h b/chromium/content/browser/download/download_net_log_parameters.h
index 9187b568b3b..0e816b37799 100644
--- a/chromium/content/browser/download/download_net_log_parameters.h
+++ b/chromium/content/browser/download/download_net_log_parameters.h
@@ -13,8 +13,6 @@
#include "content/public/browser/download_item.h"
#include "net/base/net_errors.h"
-class GURL;
-
namespace base {
class FilePath;
class Value;
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index 46c21462ac5..f23dcda4bf2 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -147,9 +147,9 @@ std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
// 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;
+ load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
else
- load_flags |= net::LOAD_PREFERRING_CACHE;
+ load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
} else {
load_flags |= net::LOAD_DISABLE_CACHE;
}
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 646911641b5..605a3b81198 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -30,7 +30,6 @@ class URLRequestStatus;
} // namespace net
namespace content {
-class DownloadManagerImpl;
class ByteStreamReader;
class ByteStreamWriter;
struct DownloadCreateInfo;
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index 1ebc62d65e7..a0acc44e3ba 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -23,6 +23,7 @@
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/resource_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/resource_response.h"
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index 28cdca50ae5..b2820a39a9f 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -25,9 +25,6 @@ class URLRequest;
namespace content {
class ByteStreamReader;
-class ByteStreamWriter;
-class DownloadRequestHandle;
-class PowerSaveBlocker;
struct DownloadCreateInfo;
// Forwards data to the download thread.
diff --git a/chromium/content/browser/download/drag_download_file.h b/chromium/content/browser/download/drag_download_file.h
index 4e2a821668f..604818a5d6c 100644
--- a/chromium/content/browser/download/drag_download_file.h
+++ b/chromium/content/browser/download/drag_download_file.h
@@ -25,7 +25,6 @@
namespace content {
-class DownloadManager;
class WebContents;
// This class implements downloading a file via dragging virtual files out of
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index bcda9fed282..0be80421848 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -12,6 +12,7 @@
#include "base/files/file.h"
#include "base/guid.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/scoped_observer.h"
#include "base/stl_util.h"
@@ -391,7 +392,6 @@ MHTMLGenerationManager* MHTMLGenerationManager::GetInstance() {
MHTMLGenerationManager::MHTMLGenerationManager() : next_job_id_(0) {}
MHTMLGenerationManager::~MHTMLGenerationManager() {
- base::STLDeleteValues(&id_to_job_);
}
void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
@@ -402,8 +402,8 @@ void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
Job* job = NewJob(web_contents, params, callback);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
"page-serialization", "SavingMhtmlJob", job, "url",
- web_contents->GetLastCommittedURL().possibly_invalid_spec().c_str(),
- "file", params.file_path.value().c_str());
+ web_contents->GetLastCommittedURL().possibly_invalid_spec(),
+ "file", params.file_path.AsUTF8Unsafe());
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
@@ -513,7 +513,6 @@ void MHTMLGenerationManager::OnFileClosed(int job_id,
base::TimeTicks::Now() - job->creation_time());
job->callback().Run(job_status == JobStatus::SUCCESS ? file_size : -1);
id_to_job_.erase(job_id);
- delete job;
}
MHTMLGenerationManager::Job* MHTMLGenerationManager::NewJob(
@@ -523,19 +522,19 @@ MHTMLGenerationManager::Job* MHTMLGenerationManager::NewJob(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Job* job = new Job(++next_job_id_, web_contents, params, callback);
- id_to_job_[job->id()] = job;
+ id_to_job_[job->id()] = base::WrapUnique(job);
return job;
}
MHTMLGenerationManager::Job* MHTMLGenerationManager::FindJob(int job_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- IDToJobMap::iterator iter = id_to_job_.find(job_id);
+ auto iter = id_to_job_.find(job_id);
if (iter == id_to_job_.end()) {
NOTREACHED();
return nullptr;
}
- return iter->second;
+ return iter->second.get();
}
void MHTMLGenerationManager::RenderProcessExited(Job* job) {
diff --git a/chromium/content/browser/download/mhtml_generation_manager.h b/chromium/content/browser/download/mhtml_generation_manager.h
index 31d9a64df62..59735022254 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.h
+++ b/chromium/content/browser/download/mhtml_generation_manager.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include <string>
@@ -88,8 +89,7 @@ class MHTMLGenerationManager {
// Called when the render process connected to a job exits.
void RenderProcessExited(Job* job);
- typedef std::map<int, Job*> IDToJobMap;
- IDToJobMap id_to_job_;
+ std::map<int, std::unique_ptr<Job>> id_to_job_;
int next_job_id_;
diff --git a/chromium/content/browser/download/mock_download_file.h b/chromium/content/browser/download/mock_download_file.h
index 7109c44c157..dcc3a43cd06 100644
--- a/chromium/content/browser/download/mock_download_file.h
+++ b/chromium/content/browser/download/mock_download_file.h
@@ -19,7 +19,6 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-struct DownloadCreateInfo;
class MockDownloadFile : public DownloadFile {
public:
diff --git a/chromium/content/browser/download/quarantine_mac.mm b/chromium/content/browser/download/quarantine_mac.mm
index e3351e2fb9c..2c0ea977755 100644
--- a/chromium/content/browser/download/quarantine_mac.mm
+++ b/chromium/content/browser/download/quarantine_mac.mm
@@ -31,8 +31,9 @@ namespace {
bool GetQuarantinePropertiesDeprecated(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties) {
+ const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
FSRef file_ref;
- if (!base::mac::FSRefFromPath(file.value(), &file_ref))
+ if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
return false;
base::ScopedCFTypeRef<CFTypeRef> quarantine_properties;
@@ -56,8 +57,9 @@ bool GetQuarantinePropertiesDeprecated(
bool SetQuarantinePropertiesDeprecated(const base::FilePath& file,
NSDictionary* properties) {
+ const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
FSRef file_ref;
- if (!base::mac::FSRefFromPath(file.value(), &file_ref))
+ if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
return false;
OSStatus os_error = LSSetItemAttribute(
&file_ref, kLSRolesAll, kLSItemQuarantineProperties, properties);
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 1603085fc23..d9d14302e31 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -66,19 +66,19 @@ void SaveFileManager::Shutdown() {
// Stop file thread operations.
void SaveFileManager::OnShutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- base::STLDeleteValues(&save_file_map_);
+ save_file_map_.clear();
}
SaveFile* SaveFileManager::LookupSaveFile(SaveItemId save_item_id) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- SaveFileMap::iterator it = save_file_map_.find(save_item_id);
- return it == save_file_map_.end() ? nullptr : it->second;
+ auto it = save_file_map_.find(save_item_id);
+ return it == save_file_map_.end() ? nullptr : it->second.get();
}
// Look up a SavePackage according to a save id.
SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SavePackageMap::iterator it = packages_.find(save_item_id);
+ auto it = packages_.find(save_item_id);
if (it != packages_.end())
return it->second;
return nullptr;
@@ -133,7 +133,7 @@ void SaveFileManager::RemoveSaveFile(SaveItemId save_item_id,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// A save page job (SavePackage) can only have one manager,
// so remove it if it exists.
- SavePackageMap::iterator it = packages_.find(save_item_id);
+ auto it = packages_.find(save_item_id);
if (it != packages_.end())
packages_.erase(it);
}
@@ -182,14 +182,14 @@ void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(info);
// No need to calculate hash.
- SaveFile* save_file = new SaveFile(info, false);
+ std::unique_ptr<SaveFile> save_file = base::MakeUnique<SaveFile>(info, false);
// TODO(phajdan.jr): We should check the return value and handle errors here.
save_file->Initialize();
+ info->path = save_file->FullPath();
DCHECK(!LookupSaveFile(info->save_item_id));
- save_file_map_[info->save_item_id] = save_file;
- info->path = save_file->FullPath();
+ save_file_map_[info->save_item_id] = std::move(save_file);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -320,7 +320,7 @@ void SaveFileManager::OnSaveURL(const GURL& url,
// So far, for saving page, we need fetch content from cache, in the
// future, maybe we can use a configuration to configure this behavior.
- request->SetLoadFlags(net::LOAD_PREFERRING_CACHE);
+ request->SetLoadFlags(net::LOAD_SKIP_CACHE_VALIDATION);
// Check if the renderer is permitted to request the requested URL.
using AuthorizationState = SaveFileResourceHandler::AuthorizationState;
@@ -362,9 +362,9 @@ void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id,
// won't exist in our map.
void SaveFileManager::CancelSave(SaveItemId save_item_id) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- SaveFileMap::iterator it = save_file_map_.find(save_item_id);
+ auto it = save_file_map_.find(save_item_id);
if (it != save_file_map_.end()) {
- SaveFile* save_file = it->second;
+ std::unique_ptr<SaveFile> save_file = std::move(it->second);
if (!save_file->InProgress()) {
// We've won a race with the UI thread--we finished the file before
@@ -386,7 +386,6 @@ void SaveFileManager::CancelSave(SaveItemId save_item_id) {
// Whatever the save file is complete or not, just delete it. This
// will delete the underlying file if InProgress() is true.
save_file_map_.erase(it);
- delete save_file;
}
}
@@ -412,12 +411,11 @@ void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
SaveItemId save_item_id = i.first;
const base::FilePath& final_name = i.second;
- SaveFileMap::iterator it = save_file_map_.find(save_item_id);
+ auto it = save_file_map_.find(save_item_id);
if (it != save_file_map_.end()) {
- SaveFile* save_file = it->second;
+ SaveFile* save_file = it->second.get();
DCHECK(!save_file->InProgress());
save_file->Rename(final_name);
- delete save_file;
save_file_map_.erase(it);
}
}
@@ -445,12 +443,11 @@ void SaveFileManager::RemoveSavedFileFromFileMap(
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
for (const SaveItemId save_item_id : save_item_ids) {
- SaveFileMap::iterator it = save_file_map_.find(save_item_id);
+ auto it = save_file_map_.find(save_item_id);
if (it != save_file_map_.end()) {
- SaveFile* save_file = it->second;
+ SaveFile* save_file = it->second.get();
DCHECK(!save_file->InProgress());
base::DeleteFile(save_file->FullPath(), false);
- delete save_file;
save_file_map_.erase(it);
}
}
diff --git a/chromium/content/browser/download/save_file_manager.h b/chromium/content/browser/download/save_file_manager.h
index 56aa46d06de..d6fd762b689 100644
--- a/chromium/content/browser/download/save_file_manager.h
+++ b/chromium/content/browser/download/save_file_manager.h
@@ -210,15 +210,12 @@ class CONTENT_EXPORT SaveFileManager
void ExecuteCancelSaveRequest(int render_process_id, int request_id);
// A map from save_item_id into SaveFiles.
- using SaveFileMap =
- std::unordered_map<SaveItemId, SaveFile*, SaveItemId::Hasher>;
- SaveFileMap save_file_map_;
+ std::unordered_map<SaveItemId, std::unique_ptr<SaveFile>, SaveItemId::Hasher>
+ save_file_map_;
// Tracks which SavePackage to send data to, called only on UI thread.
// SavePackageMap maps save item ids to their SavePackage.
- using SavePackageMap =
- std::unordered_map<SaveItemId, SavePackage*, SaveItemId::Hasher>;
- SavePackageMap packages_;
+ std::unordered_map<SaveItemId, SavePackage*, SaveItemId::Hasher> packages_;
DISALLOW_COPY_AND_ASSIGN(SaveFileManager);
};
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 09ec93883b6..d7a40941964 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -13,6 +13,7 @@
#include "base/i18n/file_util_icu.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
@@ -192,10 +193,10 @@ SavePackage::~SavePackage() {
completed_count() + in_process_count());
// Free all SaveItems.
- base::STLDeleteElements(&waiting_item_queue_);
- base::STLDeleteValues(&in_progress_items_);
- base::STLDeleteValues(&saved_success_items_);
- base::STLDeleteValues(&saved_failed_items_);
+ waiting_item_queue_.clear();
+ in_progress_items_.clear();
+ saved_success_items_.clear();
+ saved_failed_items_.clear();
// Clear containers that contain (now dangling/invalid) pointers to the
// save items freed above. This is not strictly required (as the containers
// will be destructed soon by ~SavePackage), but seems like good code hygiene.
@@ -301,10 +302,10 @@ void SavePackage::InitWithDownloadItem(
DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_);
wait_state_ = NET_FILES;
// Add this item to waiting list.
- waiting_item_queue_.push_back(new SaveItem(
+ waiting_item_queue_.push_back(base::WrapUnique(new SaveItem(
page_url_, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_NET,
FrameTreeNode::kFrameTreeNodeInvalidId,
- web_contents()->GetMainFrame()->GetFrameTreeNodeId()));
+ web_contents()->GetMainFrame()->GetFrameTreeNodeId())));
all_save_items_count_ = 1;
download_->SetTotalBytes(1);
@@ -488,13 +489,13 @@ void SavePackage::StartSave(const SaveFileCreateInfo* info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(info);
- SaveItemIdMap::iterator it = in_progress_items_.find(info->save_item_id);
+ auto it = in_progress_items_.find(info->save_item_id);
if (it == in_progress_items_.end()) {
// If not found, we must have cancel action.
DCHECK(canceled());
return;
}
- SaveItem* save_item = it->second;
+ SaveItem* save_item = it->second.get();
DCHECK(!saved_main_file_path_.empty());
@@ -556,7 +557,7 @@ SaveItem* SavePackage::LookupInProgressSaveItem(SaveItemId save_item_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto it = in_progress_items_.find(save_item_id);
if (it != in_progress_items_.end()) {
- SaveItem* save_item = it->second;
+ SaveItem* save_item = it->second.get();
DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state());
return save_item;
}
@@ -565,15 +566,16 @@ SaveItem* SavePackage::LookupInProgressSaveItem(SaveItemId save_item_id) {
void SavePackage::PutInProgressItemToSavedMap(SaveItem* save_item) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SaveItemIdMap::iterator it = in_progress_items_.find(save_item->id());
+ auto it = in_progress_items_.find(save_item->id());
DCHECK(it != in_progress_items_.end());
- DCHECK_EQ(save_item, it->second);
+ DCHECK_EQ(save_item, it->second.get());
+ std::unique_ptr<SaveItem> owned_item = std::move(it->second);
in_progress_items_.erase(it);
SaveItemIdMap& map = save_item->success() ?
saved_success_items_ : saved_failed_items_;
DCHECK(!base::ContainsKey(map, save_item->id()));
- map[save_item->id()] = save_item;
+ map[save_item->id()] = std::move(owned_item);
}
// Called for updating saving state.
@@ -610,7 +612,7 @@ void SavePackage::Stop() {
DCHECK(canceled());
if (in_process_count()) {
for (const auto& it : in_progress_items_) {
- SaveItem* save_item = it.second;
+ SaveItem* save_item = it.second.get();
DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state());
save_item->Cancel();
}
@@ -618,7 +620,7 @@ void SavePackage::Stop() {
// be put into saved_failed_items_, for successful item, they will be put
// into saved_success_items_.
while (in_process_count())
- PutInProgressItemToSavedMap(in_progress_items_.begin()->second);
+ PutInProgressItemToSavedMap(in_progress_items_.begin()->second.get());
}
// This vector contains the save ids of the save files which SaveFileManager
@@ -692,7 +694,7 @@ void SavePackage::Finish() {
// needs to remove from its |save_file_map_|.
std::vector<SaveItemId> list_of_failed_save_item_ids;
for (const auto& it : saved_failed_items_) {
- const SaveItem* save_item = it.second;
+ const SaveItem* save_item = it.second.get();
DCHECK_EQ(it.first, save_item->id());
list_of_failed_save_item_ids.push_back(save_item->id());
}
@@ -778,37 +780,39 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
do {
// Pop SaveItem from waiting list.
- SaveItem* save_item = waiting_item_queue_.front();
+ std::unique_ptr<SaveItem> save_item =
+ std::move(waiting_item_queue_.front());
+ SaveItem* save_item_ptr = save_item.get();
waiting_item_queue_.pop_front();
// Add the item to |in_progress_items_|.
DCHECK(!base::ContainsKey(in_progress_items_, save_item->id()));
- in_progress_items_[save_item->id()] = save_item;
- save_item->Start();
+ in_progress_items_[save_item_ptr->id()] = std::move(save_item);
+ save_item_ptr->Start();
// Find the frame responsible for making the network request below - it will
// be used in security checks made later by ResourceDispatcherHostImpl.
int requester_frame_tree_node_id =
- save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_NET
- ? save_item->container_frame_tree_node_id()
- : save_item->frame_tree_node_id();
+ save_item_ptr->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_NET
+ ? save_item_ptr->container_frame_tree_node_id()
+ : save_item_ptr->frame_tree_node_id();
DCHECK_NE(FrameTreeNode::kFrameTreeNodeInvalidId,
requester_frame_tree_node_id);
FrameTreeNode* requester_frame_tree_node =
FrameTreeNode::GloballyFindByID(requester_frame_tree_node_id);
if (!requester_frame_tree_node) {
- save_item->Finish(0, /* is_success = */ false);
+ save_item_ptr->Finish(0, /* is_success = */ false);
continue;
}
RenderFrameHostImpl* requester_frame =
requester_frame_tree_node->current_frame_host();
file_manager_->SaveURL(
- save_item->id(), save_item->url(), save_item->referrer(),
+ save_item_ptr->id(), save_item_ptr->url(), save_item_ptr->referrer(),
requester_frame->GetProcess()->GetID(),
requester_frame->render_view_host()->GetRoutingID(),
- requester_frame->routing_id(), save_item->save_source(),
- save_item->full_path(),
+ requester_frame->routing_id(), save_item_ptr->save_source(),
+ save_item_ptr->full_path(),
web_contents()->GetBrowserContext()->GetResourceContext(), this);
} while (process_all_remaining_items && !waiting_item_queue_.empty());
}
@@ -841,7 +845,7 @@ void SavePackage::DoSavingProcess() {
// Start a new SaveItem job if we still have job in waiting queue.
if (waiting_item_queue_.size()) {
DCHECK_EQ(NET_FILES, wait_state_);
- const SaveItem* save_item = waiting_item_queue_.front();
+ const SaveItem* save_item = waiting_item_queue_.front().get();
if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) {
SaveNextFile(false);
} else if (!in_process_count()) {
@@ -1134,7 +1138,7 @@ SaveItem* SavePackage::CreatePendingSaveItem(
SaveItem* save_item =
new SaveItem(url, sanitized_referrer, this, save_source,
save_item_frame_tree_node_id, container_frame_tree_node_id);
- waiting_item_queue_.push_back(save_item);
+ waiting_item_queue_.push_back(base::WrapUnique(save_item));
frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
.push_back(save_item);
@@ -1208,7 +1212,8 @@ void SavePackage::CompleteSavableResourceLinksResponse() {
// SAVE_FILE_FROM_DOM in the comparison function below).
std::stable_sort(
waiting_item_queue_.begin(), waiting_item_queue_.end(),
- [](SaveItem* x, SaveItem* y) {
+ [](const std::unique_ptr<SaveItem>& x,
+ const std::unique_ptr<SaveItem>& y) {
DCHECK(x);
DCHECK(y);
return (x->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) &&
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index 5cafea5461f..74ea31fc96e 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -10,6 +10,7 @@
#include <deque>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <unordered_map>
@@ -134,10 +135,8 @@ class CONTENT_EXPORT SavePackage
FRIEND_TEST_ALL_PREFIXES(SavePackageBrowserTest, ExplicitCancel);
// Map from SaveItem::id() (aka save_item_id) into a SaveItem.
- using SaveItemIdMap =
- std::unordered_map<SaveItemId, SaveItem*, SaveItemId::Hasher>;
-
- using SaveItemQueue = std::deque<SaveItem*>;
+ using SaveItemIdMap = std::
+ unordered_map<SaveItemId, std::unique_ptr<SaveItem>, SaveItemId::Hasher>;
using FileNameSet = std::set<base::FilePath::StringType,
bool (*)(base::FilePath::StringPieceType,
@@ -359,7 +358,7 @@ class CONTENT_EXPORT SavePackage
const std::string& contents_mime_type);
// A queue for items we are about to start saving.
- SaveItemQueue waiting_item_queue_;
+ std::deque<std::unique_ptr<SaveItem>> waiting_item_queue_;
// Map of all saving job in in-progress state.
SaveItemIdMap in_progress_items_;
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.h b/chromium/content/browser/fileapi/browser_file_system_helper.h
index de63da54435..c5702e73281 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.h
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.h
@@ -10,7 +10,6 @@
#include "storage/browser/fileapi/file_system_context.h"
namespace storage {
-class ExternalMountPoints;
class FileSystemContext;
class FileSystemURL;
}
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index fc2e8ddfd6d..1bc55e7407b 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -26,8 +26,8 @@ using storage::QuotaManager;
namespace content {
-// This browser test is aimed towards exercising the FileAPI bindings and
-// the actual implementation that lives in the browser side.
+// This browser test is aimed towards exercising the File System API bindings
+// and the actual implementation that lives in the browser side.
class FileSystemBrowserTest : public ContentBrowserTest {
public:
FileSystemBrowserTest() {}
diff --git a/chromium/content/browser/fileapi/fileapi_browsertest.cc b/chromium/content/browser/fileapi/fileapi_browsertest.cc
new file mode 100644
index 00000000000..e50f1569a17
--- /dev/null
+++ b/chromium/content/browser/fileapi/fileapi_browsertest.cc
@@ -0,0 +1,53 @@
+// 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 "base/path_service.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+
+namespace content {
+
+// This browser test is aimed towards exercising the FileAPI bindings and
+// the actual implementation that lives in the browser side.
+class FileAPIBrowserTest : public ContentBrowserTest {
+ public:
+ FileAPIBrowserTest() {}
+};
+
+IN_PROC_BROWSER_TEST_F(FileAPIBrowserTest, FileInputChooserParams) {
+ base::FilePath file;
+ EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ file = file.AppendASCII("bar");
+
+ NavigateToURL(shell(), GetTestUrl(".", "file_input.html"));
+
+ // Click on the <input type=file> element to launch the file upload picker.
+ {
+ std::unique_ptr<FileChooserDelegate> delegate(
+ new FileChooserDelegate(file));
+ shell()->web_contents()->SetDelegate(delegate.get());
+ EXPECT_TRUE(ExecuteScript(shell(),
+ "document.getElementById('fileinput').click();"));
+ EXPECT_TRUE(delegate->file_chosen());
+ EXPECT_TRUE(delegate->params().default_file_name.empty());
+ }
+
+ // Click again, to verify what state was maintained and what was not.
+ // The renderer is expected not to specify a default file name; it's up to
+ // the browser to remember the last selected directory in the profile.
+ {
+ std::unique_ptr<FileChooserDelegate> delegate(
+ new FileChooserDelegate(file));
+ shell()->web_contents()->SetDelegate(delegate.get());
+ EXPECT_TRUE(ExecuteScript(shell(),
+ "document.getElementById('fileinput').click();"));
+ EXPECT_TRUE(delegate->file_chosen());
+ EXPECT_TRUE(delegate->params().default_file_name.empty());
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
index 6afd9a78356..9eb3d5fac3a 100644
--- a/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -106,11 +106,11 @@ struct OriginEnumerationTestRecord {
};
const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
- {"http://example.com", false, true},
- {"http://example1.com", true, false},
- {"https://example1.com", true, true},
- {"file://", false, true},
- {"http://example.com:8000", false, true},
+ {"http://example.com/", false, true},
+ {"http://example1.com/", true, false},
+ {"https://example1.com/", true, true},
+ {"file:///", false, true},
+ {"http://example.com:8000/", false, true},
};
FileSystemURL FileSystemURLAppend(
@@ -1632,7 +1632,7 @@ TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
++i) {
const OriginEnumerationTestRecord& record =
kOriginEnumerationTestRecords[i];
- if (GURL(record.origin_url) != origin_url)
+ if (origin_url != record.origin_url)
continue;
found = true;
EXPECT_EQ(record.has_temporary,
diff --git a/chromium/content/browser/find_request_manager_browsertest.cc b/chromium/content/browser/find_request_manager_browsertest.cc
index 499d4e4e717..06024384436 100644
--- a/chromium/content/browser/find_request_manager_browsertest.cc
+++ b/chromium/content/browser/find_request_manager_browsertest.cc
@@ -356,9 +356,8 @@ INSTANTIATE_TEST_CASE_P(
FindRequestManagerTests, FindRequestManagerTest, testing::Bool());
#endif
-// TODO(crbug.com/615291): These tests sometimes fail on the
-// linux_android_rel_ng trybot.
-#if defined(OS_ANDROID) && defined(NDEBUG)
+// TODO(crbug.com/615291): These tests frequently fail on Android.
+#if defined(OS_ANDROID)
#define MAYBE(x) DISABLED_##x
#else
#define MAYBE(x) x
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 e34edcb47a9..d6fd0f756c1 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -20,7 +20,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/frame_messages.h"
#include "gpu/ipc/common/gpu_messages.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/dip_util.h"
namespace content {
@@ -129,49 +129,58 @@ void CrossProcessFrameConnector::UpdateCursor(const WebCursor& cursor) {
gfx::Point CrossProcessFrameConnector::TransformPointToRootCoordSpace(
const gfx::Point& point,
const cc::SurfaceId& surface_id) {
- return TransformPointToCoordSpaceForView(point, GetRootRenderWidgetHostView(),
- surface_id);
+ gfx::Point transformed_point;
+ TransformPointToCoordSpaceForView(point, GetRootRenderWidgetHostView(),
+ surface_id, &transformed_point);
+ return transformed_point;
}
-gfx::Point CrossProcessFrameConnector::TransformPointToLocalCoordSpace(
+bool CrossProcessFrameConnector::TransformPointToLocalCoordSpace(
const gfx::Point& point,
const cc::SurfaceId& original_surface,
- const cc::SurfaceId& local_surface_id) {
- if (original_surface == local_surface_id)
- return point;
+ const cc::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point) {
+ if (original_surface == local_surface_id) {
+ *transformed_point = point;
+ return true;
+ }
// Transformations use physical pixels rather than DIP, so conversion
// is necessary.
- gfx::Point transformed_point =
+ *transformed_point =
gfx::ConvertPointToPixel(view_->current_surface_scale_factor(), point);
cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
if (!hittest.TransformPointToTargetSurface(original_surface, local_surface_id,
- &transformed_point))
- DCHECK(false);
+ transformed_point))
+ return false;
- return gfx::ConvertPointToDIP(view_->current_surface_scale_factor(),
- transformed_point);
+ *transformed_point = gfx::ConvertPointToDIP(
+ view_->current_surface_scale_factor(), *transformed_point);
+ return true;
}
-gfx::Point CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
+bool CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
const gfx::Point& point,
RenderWidgetHostViewBase* target_view,
- const cc::SurfaceId& local_surface_id) {
+ const cc::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point) {
RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
if (!root_view)
- return point;
+ return false;
// It is possible that neither the original surface or target surface is an
// ancestor of the other in the RenderWidgetHostView tree (e.g. they could
- // be siblings). To account for this, the point is first tranformed into the
+ // be siblings). To account for this, the point is first transformed into the
// root coordinate space and then the root is asked to perform the conversion.
- gfx::Point root_point =
- root_view->TransformPointToLocalCoordSpace(point, local_surface_id);
+ if (!root_view->TransformPointToLocalCoordSpace(point, local_surface_id,
+ transformed_point))
+ return false;
if (target_view == root_view)
- return root_point;
+ return true;
- return root_view->TransformPointToCoordSpaceForView(point, target_view);
+ return root_view->TransformPointToCoordSpaceForView(
+ *transformed_point, target_view, transformed_point);
}
void CrossProcessFrameConnector::ForwardProcessAckedTouchEvent(
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 1eb930492df..2b2160d135e 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -29,7 +29,6 @@ class Message;
namespace content {
class RenderFrameProxyHost;
-class RenderWidgetHostImpl;
class RenderWidgetHostViewBase;
class RenderWidgetHostViewChildFrame;
class WebCursor;
@@ -97,16 +96,19 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
const cc::SurfaceId& surface_id);
// TransformPointToLocalCoordSpace() can only transform points between
// surfaces where one is embedded (not necessarily directly) within the
- // other. For points that can be in sibling surfaces, they must first be
- // converted to the root surface's coordinate space.
- gfx::Point TransformPointToLocalCoordSpace(
- const gfx::Point& point,
- const cc::SurfaceId& original_surface,
- const cc::SurfaceId& local_surface_id);
- gfx::Point TransformPointToCoordSpaceForView(
- const gfx::Point& point,
- RenderWidgetHostViewBase* target_view,
- const cc::SurfaceId& local_surface_id);
+ // 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.
+ bool TransformPointToLocalCoordSpace(const gfx::Point& point,
+ const cc::SurfaceId& original_surface,
+ const cc::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 cc::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point);
// Pass acked touch events to the root view for gesture processing.
void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
diff --git a/chromium/content/browser/frame_host/cross_site_transferring_request.cc b/chromium/content/browser/frame_host/cross_site_transferring_request.cc
deleted file mode 100644
index 1a34fe72158..00000000000
--- a/chromium/content/browser/frame_host/cross_site_transferring_request.cc
+++ /dev/null
@@ -1,46 +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/frame_host/cross_site_transferring_request.h"
-
-#include "base/logging.h"
-#include "content/browser/loader/cross_site_resource_handler.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-namespace {
-
-void CancelRequestOnIOThread(GlobalRequestID global_request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- ResourceDispatcherHostImpl::Get()->CancelTransferringNavigation(
- global_request_id);
-}
-
-} // namespace
-
-CrossSiteTransferringRequest::CrossSiteTransferringRequest(
- GlobalRequestID global_request_id)
- : global_request_id_(global_request_id) {
- DCHECK(global_request_id_ != GlobalRequestID());
-}
-
-CrossSiteTransferringRequest::~CrossSiteTransferringRequest() {
- if (global_request_id_ == GlobalRequestID())
- return;
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&CancelRequestOnIOThread, global_request_id_));
-}
-
-void CrossSiteTransferringRequest::ReleaseRequest() {
- DCHECK_NE(-1, global_request_id_.child_id);
- DCHECK_NE(-1, global_request_id_.request_id);
- global_request_id_ = GlobalRequestID();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/frame_host/cross_site_transferring_request.h b/chromium/content/browser/frame_host/cross_site_transferring_request.h
deleted file mode 100644
index 2d5d9228359..00000000000
--- a/chromium/content/browser/frame_host/cross_site_transferring_request.h
+++ /dev/null
@@ -1,42 +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_FRAME_HOST_CROSS_SITE_TRANSFERRING_REQUEST_H_
-#define CONTENT_BROWSER_FRAME_HOST_CROSS_SITE_TRANSFERRING_REQUEST_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/global_request_id.h"
-
-namespace content {
-
-class CrossSiteResourceHandler;
-
-// A UI thread object that owns a request being transferred. Deleting the
-// object without releasing the request will delete the underlying URLRequest.
-// This is needed to clean up the URLRequest when a cross site navigation is
-// cancelled.
-class CONTENT_EXPORT CrossSiteTransferringRequest {
- public:
- explicit CrossSiteTransferringRequest(GlobalRequestID global_request_id);
- ~CrossSiteTransferringRequest();
-
- // Relinquishes ownership of the request, so another process can take
- // control of it.
- void ReleaseRequest();
-
- GlobalRequestID request_id() const { return global_request_id_; }
-
- private:
- // No need for a weak pointer here - nothing should have ownership of the
- // cross site request until after |this| is deleted, or ReleaseRequest is
- // called.
- GlobalRequestID global_request_id_;
-
- DISALLOW_COPY_AND_ASSIGN(CrossSiteTransferringRequest);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FRAME_HOST_CROSS_SITE_TRANSFERRING_REQUEST_H_
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index 1ff19d5c7e8..2e61cc1abc5 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -56,7 +56,7 @@ const char kKaskoSendReport[] = "/send-report";
void HandlePpapiFlashDebugURL(const GURL& url) {
#if defined(ENABLE_PLUGINS)
- bool crash = url == GURL(kChromeUIPpapiFlashCrashURL);
+ bool crash = url == kChromeUIPpapiFlashCrashURL;
std::vector<PpapiPluginProcessHost*> hosts;
PpapiPluginProcessHost::FindByName(
@@ -75,7 +75,7 @@ bool IsKaskoDebugURL(const GURL& url) {
#if BUILDFLAG(ENABLE_KASKO)
return (url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
url.DomainIs(kKaskoCrashDomain) &&
- url.path() == kKaskoSendReport);
+ url.path_piece() == kKaskoSendReport);
#else
return false;
#endif
@@ -127,14 +127,17 @@ bool IsAsanDebugURL(const GURL& url) {
return false;
}
- if (url.path() == kAsanHeapOverflow || url.path() == kAsanHeapUnderflow ||
- url.path() == kAsanUseAfterFree) {
+ if (url.path_piece() == kAsanHeapOverflow ||
+ url.path_piece() == kAsanHeapUnderflow ||
+ url.path_piece() == kAsanUseAfterFree) {
return true;
}
#if defined(SYZYASAN)
- if (url.path() == kAsanCorruptHeapBlock || url.path() == kAsanCorruptHeap)
+ if (url.path_piece() == kAsanCorruptHeapBlock ||
+ url.path_piece() == kAsanCorruptHeap) {
return true;
+ }
#endif
return false;
@@ -145,21 +148,21 @@ bool HandleAsanDebugURL(const GURL& url) {
if (!base::debug::IsBinaryInstrumented())
return false;
- if (url.path() == kAsanCorruptHeapBlock) {
+ if (url.path_piece() == kAsanCorruptHeapBlock) {
base::debug::AsanCorruptHeapBlock();
return true;
- } else if (url.path() == kAsanCorruptHeap) {
+ } else if (url.path_piece() == kAsanCorruptHeap) {
base::debug::AsanCorruptHeap();
return true;
}
#endif
#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
- if (url.path() == kAsanHeapOverflow) {
+ if (url.path_piece() == kAsanHeapOverflow) {
base::debug::AsanHeapOverflow();
- } else if (url.path() == kAsanHeapUnderflow) {
+ } else if (url.path_piece() == kAsanHeapUnderflow) {
base::debug::AsanHeapUnderflow();
- } else if (url.path() == kAsanUseAfterFree) {
+ } else if (url.path_piece() == kAsanUseAfterFree) {
base::debug::AsanHeapUseAfterFree();
} else {
return false;
@@ -198,18 +201,18 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
return true;
}
- if (url == GURL(kChromeUIBrowserCrashURL)) {
+ if (url == kChromeUIBrowserCrashURL) {
// Induce an intentional crash in the browser process.
CHECK(false);
return true;
}
- if (url == GURL(kChromeUIBrowserUIHang)) {
+ if (url == kChromeUIBrowserUIHang) {
HangCurrentThread();
return true;
}
- if (url == GURL(kChromeUIDelayedBrowserUIHang)) {
+ if (url == kChromeUIDelayedBrowserUIHang) {
// Webdriver-safe url to hang the ui thread. Webdriver waits for the onload
// event in javascript which needs a little more time to fire.
BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
@@ -218,29 +221,28 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
return true;
}
- if (url == GURL(kChromeUIGpuCleanURL)) {
+ if (url == kChromeUIGpuCleanURL) {
GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
if (shim)
shim->SimulateRemoveAllContext();
return true;
}
- if (url == GURL(kChromeUIGpuCrashURL)) {
+ if (url == kChromeUIGpuCrashURL) {
GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
if (shim)
shim->SimulateCrash();
return true;
}
- if (url == GURL(kChromeUIGpuHangURL)) {
+ if (url == kChromeUIGpuHangURL) {
GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
if (shim)
shim->SimulateHang();
return true;
}
- if (url == GURL(kChromeUIPpapiFlashCrashURL) ||
- url == GURL(kChromeUIPpapiFlashHangURL)) {
+ if (url == kChromeUIPpapiFlashCrashURL || url == kChromeUIPpapiFlashHangURL) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&HandlePpapiFlashDebugURL, url));
return true;
@@ -256,13 +258,13 @@ bool IsRendererDebugURL(const GURL& url) {
if (url.SchemeIs(url::kJavaScriptScheme))
return true;
- return url == GURL(kChromeUIBadCastCrashURL) ||
- url == GURL(kChromeUICrashURL) ||
- url == GURL(kChromeUIDumpURL) ||
- url == GURL(kChromeUIKillURL) ||
- url == GURL(kChromeUIHangURL) ||
- url == GURL(kChromeUIShorthangURL) ||
- url == GURL(kChromeUIMemoryExhaustURL);
+ return url == kChromeUIBadCastCrashURL ||
+ url == kChromeUICrashURL ||
+ url == kChromeUIDumpURL ||
+ url == kChromeUIKillURL ||
+ url == kChromeUIHangURL ||
+ url == kChromeUIShorthangURL ||
+ url == kChromeUIMemoryExhaustURL;
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index 511454f4d10..48bc7137a28 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -109,7 +109,7 @@ FrameTree::FrameTree(Navigator* navigator,
std::string(),
std::string(),
FrameOwnerProperties())),
- focused_frame_tree_node_id_(-1),
+ focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
load_progress_(0.0) {}
FrameTree::~FrameTree() {
@@ -264,18 +264,6 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
if (node == GetFocusedFrame())
return;
- if (!node) {
- // TODO(avallee): https://crbug.com/614463 Notify proxies here once
- // <webview> supports oopifs inside itself.
- if (GetFocusedFrame())
- GetFocusedFrame()->current_frame_host()->ClearFocusedFrame();
- focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
-
- // TODO(avallee): https://crbug.com/610795 This line is not sufficient to
- // make the test pass. There seems to be no focus change events generated.
- root()->current_frame_host()->UpdateAXTreeData();
- return;
- }
std::set<SiteInstance*> frame_tree_site_instances =
CollectSiteInstances(this);
@@ -381,7 +369,7 @@ void FrameTree::ReleaseRenderViewHostRef(RenderViewHostImpl* render_view_host) {
void FrameTree::FrameRemoved(FrameTreeNode* frame) {
if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
- focused_frame_tree_node_id_ = -1;
+ focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
// No notification for the root frame.
if (!frame->parent()) {
@@ -418,7 +406,7 @@ void FrameTree::UpdateLoadProgress() {
// Ignore the current frame if it has not started loading,
// if the frame is cross-origin, or about:blank.
if (!node->has_started_loading() || !node->HasSameOrigin(*root_) ||
- node->current_url() == GURL(url::kAboutBlankURL))
+ node->current_url() == url::kAboutBlankURL)
continue;
progress += node->loading_progress();
frame_count++;
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index 73ba7cb34c9..61ea016f865 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -22,7 +22,6 @@ namespace content {
struct FrameOwnerProperties;
class Navigator;
class RenderFrameHostDelegate;
-class RenderProcessHost;
class RenderViewHostDelegate;
class RenderViewHostImpl;
class RenderFrameHostManager;
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index bc3078e158c..8dea25ba20e 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -20,7 +20,6 @@
#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/content_browser_test_utils_internal.h"
-#include "content/test/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
@@ -50,8 +49,8 @@ class FrameTreeBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
private:
@@ -323,6 +322,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
FrameTreeNode* target = root->child_at(0)->child_at(0);
std::string blob_url_string;
+ RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
EXPECT_TRUE(ExecuteScriptAndExtractString(
root,
"function receiveMessage(event) {"
@@ -337,6 +337,9 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
"var blob_url = URL.createObjectURL(blob);"
"frames[0][0].location.href = blob_url;",
&blob_url_string));
+ // Wait for the RenderFrame to go away, if this will be cross-process.
+ if (AreAllSitesIsolatedForTesting())
+ deleted_observer.WaitUntilDeleted();
EXPECT_EQ(GURL(blob_url_string), target->current_url());
EXPECT_EQ(url::kBlobScheme, target->current_url().scheme());
EXPECT_FALSE(target->current_origin().unique());
@@ -591,8 +594,8 @@ class CrossProcessFrameTreeBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
private:
@@ -710,8 +713,8 @@ class IsolateIcelandFrameTreeBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
private:
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index 9d6eac59956..e37dd7be76d 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -121,12 +121,20 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
FrameTreeNode::~FrameTreeNode() {
std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
frame_tree_->FrameRemoved(this);
- FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeDestroyed(this));
+ for (auto& observer : observers_)
+ observer.OnFrameTreeNodeDestroyed(this);
if (opener_)
opener_->RemoveObserver(opener_observer_.get());
g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
+
+ if (navigation_request_) {
+ // PlzNavigate: if a frame with a pending navigation is detached, make sure
+ // the WebContents (and its observers) update their loading state.
+ navigation_request_.reset();
+ DidStopLoading();
+ }
}
void FrameTreeNode::AddObserver(Observer* observer) {
@@ -153,7 +161,7 @@ FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
child->render_manager()->Init(
render_manager_.current_host()->GetSiteInstance(),
render_manager_.current_host()->GetRoutingID(), frame_routing_id,
- MSG_ROUTING_NONE);
+ MSG_ROUTING_NONE, false);
// Other renderer processes in this BrowsingInstance may need to find out
// about the new frame. Create a proxy for the child frame in all
@@ -205,7 +213,7 @@ void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
}
void FrameTreeNode::SetCurrentURL(const GURL& url) {
- if (!has_committed_real_load_ && url != GURL(url::kAboutBlankURL))
+ if (!has_committed_real_load_ && url != url::kAboutBlankURL)
has_committed_real_load_ = true;
current_frame_host()->set_last_committed_url(url);
blame_context_.TakeSnapshot();
@@ -465,7 +473,8 @@ bool FrameTreeNode::StopLoading() {
void FrameTreeNode::DidFocus() {
last_focus_time_ = base::TimeTicks::Now();
- FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeFocused(this));
+ for (auto& observer : observers_)
+ observer.OnFrameTreeNodeFocused(this);
}
void FrameTreeNode::BeforeUnloadCanceled() {
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index 78650a3c66f..4fbe4425e62 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -78,7 +78,8 @@ class InterstitialPageImpl::InterstitialPageRVHDelegateView
WebDragOperationsMask operations_allowed,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
@@ -151,7 +152,6 @@ InterstitialPageImpl::InterstitialPageImpl(
url_(url),
new_navigation_(new_navigation),
should_discard_pending_nav_entry_(new_navigation),
- reload_on_dont_proceed_(false),
enabled_(true),
action_taken_(NO_ACTION),
render_view_host_(NULL),
@@ -235,7 +235,8 @@ void InterstitialPageImpl::Show() {
controller_->SetTransientEntry(std::move(entry));
- static_cast<WebContentsImpl*>(web_contents_)->DidChangeVisibleSSLState();
+ static_cast<WebContentsImpl*>(web_contents_)
+ ->DidChangeVisibleSecurityState();
}
DCHECK(!render_view_host_);
@@ -301,7 +302,7 @@ void InterstitialPageImpl::Hide() {
if (entry && !new_navigation_ && should_revert_web_contents_title_)
web_contents_->UpdateTitleForEntry(entry, original_web_contents_title_);
- static_cast<WebContentsImpl*>(web_contents_)->DidChangeVisibleSSLState();
+ static_cast<WebContentsImpl*>(web_contents_)->DidChangeVisibleSecurityState();
InterstitialPageMap::iterator iter =
g_web_contents_to_interstitial_page->find(web_contents_);
@@ -381,7 +382,6 @@ void InterstitialPageImpl::RenderFrameCreated(
void InterstitialPageImpl::UpdateTitle(
RenderFrameHost* render_frame_host,
- int32_t page_id,
const base::string16& title,
base::i18n::TextDirection title_direction) {
if (!enabled())
@@ -577,7 +577,7 @@ RenderViewHostImpl* InterstitialPageImpl::CreateRenderViewHost() {
int32_t widget_routing_id = site_instance->GetProcess()->GetNextRoutingID();
frame_tree_.root()->render_manager()->Init(
site_instance.get(), widget_routing_id, MSG_ROUTING_NONE,
- widget_routing_id);
+ widget_routing_id, false);
return frame_tree_.root()->current_frame_host()->render_view_host();
}
@@ -591,11 +591,8 @@ WebContentsView* InterstitialPageImpl::CreateWebContentsView() {
RenderWidgetHostImpl::From(render_view_host_->GetWidget())->SetView(view);
render_view_host_->AllowBindings(BINDINGS_POLICY_DOM_AUTOMATION);
- int32_t max_page_id = web_contents()->GetMaxPageIDForSiteInstance(
- render_view_host_->GetSiteInstance());
render_view_host_->CreateRenderView(MSG_ROUTING_NONE,
MSG_ROUTING_NONE,
- max_page_id,
FrameReplicationState(),
false);
controller_->delegate()->RenderFrameForInterstitialPageCreated(
@@ -671,9 +668,6 @@ void InterstitialPageImpl::DontProceed() {
controller_->DiscardNonCommittedEntries();
}
- if (reload_on_dont_proceed_)
- controller_->Reload(true);
-
Hide();
delegate_->OnDontProceed();
}
@@ -890,8 +884,10 @@ void InterstitialPageImpl::InterstitialPageRVHDelegateView::StartDragging(
WebDragOperationsMask allowed_operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
- interstitial_page_->render_view_host_->DragSourceSystemDragEnded();
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
+ interstitial_page_->render_view_host_->GetWidget()->
+ DragSourceSystemDragEnded();
DVLOG(1) << "InterstitialPage does not support dragging yet.";
}
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 9866b474d5f..53498806915 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -88,12 +88,6 @@ class CONTENT_EXPORT InterstitialPageImpl
RenderWidgetHostView* GetView();
- // See description above field.
- void set_reload_on_dont_proceed(bool value) {
- reload_on_dont_proceed_ = value;
- }
- bool reload_on_dont_proceed() const { return reload_on_dont_proceed_; }
-
bool pause_throbber() const { return pause_throbber_; }
// TODO(nasko): This should move to InterstitialPageNavigatorImpl, but in
@@ -113,7 +107,6 @@ class CONTENT_EXPORT InterstitialPageImpl
const IPC::Message& message) override;
void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
void UpdateTitle(RenderFrameHost* render_frame_host,
- int32_t page_id,
const base::string16& title,
base::i18n::TextDirection title_direction) override;
InterstitialPage* GetAsInterstitialPage() override;
@@ -252,12 +245,6 @@ class CONTENT_EXPORT InterstitialPageImpl
// not discard it.
bool should_discard_pending_nav_entry_;
- // If true and the user chooses not to proceed the target NavigationController
- // is reloaded. This is used when two NavigationControllers are merged
- // (CopyStateFromAndPrune).
- // The default is false.
- bool reload_on_dont_proceed_;
-
// Whether this interstitial is enabled. See Disable() for more info.
bool enabled_;
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
index a19deefa127..3c3c7ac0cf3 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -32,25 +32,25 @@ void InterstitialPageNavigatorImpl::DidStartProvisionalLoad(
const GURL& url,
const base::TimeTicks& navigation_start) {
// The interstitial page should only navigate once.
- DCHECK(!navigation_handle_.get());
- navigation_handle_ =
+ DCHECK(!render_frame_host->navigation_handle());
+ render_frame_host->SetNavigationHandle(
NavigationHandleImpl::Create(url, render_frame_host->frame_tree_node(),
false, // is_renderer_initiated
false, // is_synchronous
false, // is_srcdoc
navigation_start,
- 0, // pending_nav_entry_id
- false); // started_in_context_menu
+ 0, // pending_nav_entry_id
+ false) // started_in_context_menu
+ );
}
void InterstitialPageNavigatorImpl::DidNavigate(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) {
- if (navigation_handle_) {
- navigation_handle_->DidCommitNavigation(input_params, false,
- render_frame_host);
- navigation_handle_.reset();
- }
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params,
+ std::unique_ptr<NavigationHandleImpl> navigation_handle) {
+ navigation_handle->DidCommitNavigation(input_params, false,
+ render_frame_host);
+ navigation_handle.reset();
// TODO(nasko): Move implementation here, but for the time being call out
// to the interstitial page code.
@@ -58,10 +58,4 @@ void InterstitialPageNavigatorImpl::DidNavigate(
input_params);
}
-NavigationHandleImpl*
-InterstitialPageNavigatorImpl::GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host) {
- return navigation_handle_.get();
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
index 9ef3bbf28b0..92afa5f0788 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
@@ -30,11 +30,10 @@ class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator {
RenderFrameHostImpl* render_frame_host,
const GURL& url,
const base::TimeTicks& navigation_start) override;
- void DidNavigate(RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params&
- input_params) override;
- NavigationHandleImpl* GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host) override;
+ void DidNavigate(
+ RenderFrameHostImpl* render_frame_host,
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params,
+ std::unique_ptr<NavigationHandleImpl> navigation_handle) override;
private:
~InterstitialPageNavigatorImpl() override;
@@ -46,15 +45,6 @@ class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator {
// The NavigationController associated with this navigator.
NavigationControllerImpl* controller_;
- // The NavigationHandle associated with the interstitial navigation.
- // Interstitials are assumed to only have a single RenderFrameHost, so it's ok
- // to track the NavigationHandle here rather than per-frame.
- //
- // Note: this NavigationHandleImpl will not send DidStartNavigation or
- // DidFinishNavigation events to the WebContentsObserver, since those will go
- // through InterstitialPageImpl as the NavigatorDelegate and get dropped.
- std::unique_ptr<NavigationHandleImpl> navigation_handle_;
-
DISALLOW_COPY_AND_ASSIGN(InterstitialPageNavigatorImpl);
};
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
index 2a28c22669b..60df123f4c8 100644
--- a/chromium/content/browser/frame_host/navigation_controller_delegate.h
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -15,16 +15,12 @@
namespace content {
struct LoadCommittedDetails;
-struct LoadNotificationDetails;
-struct NativeWebKeyboardEvent;
class FrameTree;
class InterstitialPage;
class InterstitialPageImpl;
class RenderFrameHost;
class RenderViewHost;
-class SiteInstance;
class WebContents;
-class WebContentsDelegate;
// Interface for objects embedding a NavigationController to provide the
// functionality NavigationController needs.
@@ -40,8 +36,6 @@ class NavigationControllerDelegate {
virtual const std::string& GetContentsMimeType() const = 0;
virtual void NotifyNavigationStateChanged(InvalidateTypes changed_flags) = 0;
virtual void Stop() = 0;
- virtual int32_t GetMaxPageID() = 0;
- virtual int32_t GetMaxPageIDForSiteInstance(SiteInstance* site_instance) = 0;
virtual bool IsBeingDestroyed() const = 0;
virtual bool CanOverscrollContent() const = 0;
@@ -53,10 +47,6 @@ class NavigationControllerDelegate {
const LoadCommittedDetails& load_details) = 0;
virtual void SetHistoryOffsetAndLength(int history_offset,
int history_length) = 0;
- virtual void CopyMaxPageIDsFrom(WebContents* web_contents) = 0;
- virtual void UpdateMaxPageID(int32_t page_id) = 0;
- virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
- int32_t page_id) = 0;
virtual void ActivateAndShowRepostFormWarningDialog() = 0;
virtual bool HasAccessedInitialDocument() = 0;
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 31385c79d4e..42d6032375f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -175,7 +175,6 @@ std::unique_ptr<NavigationEntry> NavigationController::CreateNavigationEntry(
NavigationEntryImpl* entry = new NavigationEntryImpl(
NULL, // The site instance for tabs is sent on navigation
// (WebContents::GetSiteInstance).
- -1,
loaded_url,
referrer,
base::string16(),
@@ -219,7 +218,6 @@ NavigationControllerImpl::NavigationControllerImpl(
pending_entry_index_(-1),
transient_entry_index_(-1),
delegate_(delegate),
- max_restored_page_id_(-1),
ssl_manager_(this),
needs_reload_(false),
is_initial_navigation_(true),
@@ -275,12 +273,7 @@ void NavigationControllerImpl::Reload(bool check_for_repost) {
ReloadInternal(check_for_repost, type);
}
void NavigationControllerImpl::ReloadToRefreshContent(bool check_for_repost) {
- ReloadType type = ReloadType::NORMAL;
- if (base::FeatureList::IsEnabled(
- features::kNonValidatingReloadOnRefreshContent)) {
- type = ReloadType::MAIN_RESOURCE;
- }
- ReloadInternal(check_for_repost, type);
+ ReloadInternal(check_for_repost, ReloadType::MAIN_RESOURCE);
}
void NavigationControllerImpl::ReloadBypassingCache(bool check_for_repost) {
ReloadInternal(check_for_repost, ReloadType::BYPASSING_CACHE);
@@ -366,12 +359,11 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
DiscardNonCommittedEntriesInternal();
// If we are reloading an entry that no longer belongs to the current
- // site instance (for example, refreshing a page for just installed app),
- // the reload must happen in a new process.
- // The new entry must have a new page_id and site instance, so it behaves
- // as new navigation (which happens to clear forward history).
- // Tabs that are discarded due to low memory conditions may not have a site
- // instance, and should not be treated as a cross-site reload.
+ // SiteInstance (for example, refreshing a page for just installed app), the
+ // reload must happen in a new process. The new entry behaves as new
+ // navigation (which happens to clear forward history). Tabs that are
+ // discarded due to low memory conditions may not have a SiteInstance, and
+ // should not be treated as a cross-site reload.
SiteInstanceImpl* site_instance = entry->site_instance();
// Permit reloading guests without further checks.
bool is_for_guests_only = site_instance && site_instance->HasProcess() &&
@@ -434,13 +426,6 @@ bool NavigationControllerImpl::IsInitialBlankNavigation() const {
return IsInitialNavigation() && GetEntryCount() == 0;
}
-NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID(
- SiteInstance* instance,
- int32_t page_id) const {
- int index = GetEntryIndexWithPageID(instance, page_id);
- return (index != -1) ? entries_[index].get() : nullptr;
-}
-
NavigationEntryImpl*
NavigationControllerImpl::GetEntryWithUniqueID(int nav_entry_id) const {
int index = GetEntryIndexWithUniqueID(nav_entry_id);
@@ -723,7 +708,6 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
// new FrameNavigationEntry for the target subframe.
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
entry = GetLastCommittedEntry()->Clone();
- entry->SetPageID(-1);
entry->AddOrUpdateFrameEntry(
node, -1, -1, nullptr,
static_cast<SiteInstanceImpl*>(params.source_site_instance.get()),
@@ -797,7 +781,8 @@ bool NavigationControllerImpl::RendererDidNavigate(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
LoadCommittedDetails* details,
- bool is_navigation_within_page) {
+ bool is_navigation_within_page,
+ NavigationHandleImpl* navigation_handle) {
is_initial_navigation_ = false;
// Save the previous state before we clobber it.
@@ -828,7 +813,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
// Save reload type and timestamp for a reload navigation to detect
// consecutive reloads when the next reload is requested.
- if (PendingEntryMatchesHandle(rfh->navigation_handle())) {
+ if (PendingEntryMatchesHandle(navigation_handle)) {
if (pending_entry_->reload_type() != ReloadType::NONE) {
last_committed_reload_type_ = pending_entry_->reload_type();
last_committed_reload_time_ =
@@ -843,14 +828,16 @@ bool NavigationControllerImpl::RendererDidNavigate(
switch (details->type) {
case NAVIGATION_TYPE_NEW_PAGE:
RendererDidNavigateToNewPage(rfh, params, details->is_in_page,
- details->did_replace_entry);
+ details->did_replace_entry,
+ navigation_handle);
break;
case NAVIGATION_TYPE_EXISTING_PAGE:
details->did_replace_entry = details->is_in_page;
- RendererDidNavigateToExistingPage(rfh, params, details->is_in_page);
+ RendererDidNavigateToExistingPage(rfh, params, details->is_in_page,
+ navigation_handle);
break;
case NAVIGATION_TYPE_SAME_PAGE:
- RendererDidNavigateToSamePage(rfh, params);
+ RendererDidNavigateToSamePage(rfh, params, navigation_handle);
break;
case NAVIGATION_TYPE_NEW_SUBFRAME:
RendererDidNavigateNewSubframe(rfh, params, details->is_in_page,
@@ -1079,7 +1066,8 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
bool is_in_page,
- bool replace_entry) {
+ bool replace_entry,
+ NavigationHandleImpl* handle) {
std::unique_ptr<NavigationEntryImpl> new_entry;
bool update_virtual_url = false;
@@ -1104,17 +1092,13 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
// Only make a copy of the pending entry if it is appropriate for the new page
// that was just loaded. Verify this by checking if the entry corresponds
- // to the current navigation handle. Note that in some tests the render frame
- // host does not have a valid handle. Additionally, coarsely check that:
+ // to the given navigation handle. Additionally, coarsely check that:
// 1. The SiteInstance hasn't been assigned to something else.
// 2. The pending entry was intended as a new entry, rather than being a
// history navigation that was interrupted by an unrelated,
// renderer-initiated navigation.
// TODO(csharrison): Investigate whether we can remove some of the coarser
// checks.
- NavigationHandleImpl* handle = rfh->navigation_handle();
- DCHECK(handle);
-
if (!new_entry &&
PendingEntryMatchesHandle(handle) && pending_entry_index_ == -1 &&
(!pending_entry_->site_instance() ||
@@ -1155,7 +1139,6 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
if (update_virtual_url)
UpdateVirtualURLToURL(new_entry.get(), params.url);
new_entry->SetReferrer(params.referrer);
- new_entry->SetPageID(params.page_id);
new_entry->SetTransitionType(params.transition);
new_entry->set_site_instance(
static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance()));
@@ -1195,7 +1178,8 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
void NavigationControllerImpl::RendererDidNavigateToExistingPage(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
- bool is_in_page) {
+ bool is_in_page,
+ NavigationHandleImpl* handle) {
// We should only get here for main frame navigations.
DCHECK(!rfh->GetParent());
@@ -1203,7 +1187,6 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
// in https://crbug.com/596707.
NavigationEntryImpl* entry;
- NavigationHandleImpl* handle = rfh->navigation_handle();
if (params.intended_as_new_entry) {
// This was intended as a new entry but the pending entry was lost in the
// meanwhile and no new page was created. We are stuck at the last committed
@@ -1276,7 +1259,8 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
void NavigationControllerImpl::RendererDidNavigateToSamePage(
RenderFrameHostImpl* rfh,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ NavigationHandleImpl* handle) {
// This classification says that we have a pending entry that's the same as
// the last committed entry. This entry is guaranteed to exist by
// ClassifyNavigation. All we need to do is update the existing entry.
@@ -1301,7 +1285,7 @@ void NavigationControllerImpl::RendererDidNavigateToSamePage(
// If a user presses enter in the omnibox and the server redirects, the URL
// might change (but it's still considered a SAME_PAGE navigation). So we must
// update the SSL status.
- existing_entry->GetSSL() = rfh->navigation_handle()->ssl_status();
+ existing_entry->GetSSL() = handle->ssl_status();
// The extra headers may have changed due to reloading with different headers.
existing_entry->set_extra_headers(pending_entry_->extra_headers());
@@ -1351,7 +1335,6 @@ void NavigationControllerImpl::RendererDidNavigateNewSubframe(
new_entry = GetLastCommittedEntry()->Clone();
}
- new_entry->SetPageID(params.page_id);
InsertOrReplaceEntry(std::move(new_entry), replace_entry);
}
@@ -1476,7 +1459,7 @@ bool NavigationControllerImpl::IsURLInPageNavigation(
// We don't have sufficient information to identify
// that case at the moment, so always allow about:blank
// for now.
- last_committed_url == GURL(url::kAboutBlankURL) ||
+ last_committed_url == url::kAboutBlankURL ||
last_committed_url.GetOrigin() == url.GetOrigin() ||
committed_origin == origin ||
!prefs.web_security_enabled ||
@@ -1513,11 +1496,6 @@ void NavigationControllerImpl::CopyStateFrom(
FinishRestore(source.last_committed_entry_index_,
RestoreType::CURRENT_SESSION);
-
- // Copy the max page id map from the old tab to the new tab. This ensures
- // that new and existing navigations in the tab's current SiteInstances
- // are identified properly.
- delegate_->CopyMaxPageIDsFrom(source.delegate()->GetWebContents());
}
void NavigationControllerImpl::CopyStateFromAndPrune(
@@ -1560,17 +1538,6 @@ void NavigationControllerImpl::CopyStateFromAndPrune(
delegate_->SetHistoryOffsetAndLength(last_committed_entry_index_,
GetEntryCount());
-
- // Copy the max page id map from the old tab to the new tab. This ensures that
- // new and existing navigations in the tab's current SiteInstances are
- // identified properly.
- NavigationEntryImpl* last_committed = GetLastCommittedEntry();
- int32_t site_max_page_id =
- delegate_->GetMaxPageIDForSiteInstance(last_committed->site_instance());
- delegate_->CopyMaxPageIDsFrom(source->delegate()->GetWebContents());
- delegate_->UpdateMaxPageIDForSiteInstance(last_committed->site_instance(),
- site_max_page_id);
- max_restored_page_id_ = source->max_restored_page_id_;
}
bool NavigationControllerImpl::CanPruneAllButLastCommitted() {
@@ -1637,14 +1604,6 @@ void NavigationControllerImpl::SetSessionStorageNamespace(
CHECK(successful_insert) << "Cannot replace existing SessionStorageNamespace";
}
-void NavigationControllerImpl::SetMaxRestoredPageID(int32_t max_id) {
- max_restored_page_id_ = max_id;
-}
-
-int32_t NavigationControllerImpl::GetMaxRestoredPageID() const {
- return max_restored_page_id_;
-}
-
bool NavigationControllerImpl::IsUnmodifiedBlankTab() const {
return IsInitialNavigation() &&
!GetLastCommittedEntry() &&
@@ -1760,12 +1719,7 @@ void NavigationControllerImpl::InsertOrReplaceEntry(
// When replacing, don't prune the forward history.
if (replace && current_size > 0) {
- int32_t page_id = entry->GetPageID();
-
entries_[last_committed_entry_index_] = std::move(entry);
-
- // This is a new page ID, so we need everybody to know about it.
- delegate_->UpdateMaxPageID(page_id);
return;
}
@@ -1789,12 +1743,8 @@ void NavigationControllerImpl::InsertOrReplaceEntry(
PruneOldestEntryIfFull();
- int32_t page_id = entry->GetPageID();
entries_.push_back(std::move(entry));
last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
-
- // This is a new page ID, so we need everybody to know about it.
- delegate_->UpdateMaxPageID(page_id);
}
void NavigationControllerImpl::PruneOldestEntryIfFull() {
@@ -2055,8 +2005,6 @@ void NavigationControllerImpl::FinishRestore(int selected_index,
DCHECK(selected_index >= 0 && selected_index < GetEntryCount());
ConfigureEntriesForRestore(&entries_, type);
- SetMaxRestoredPageID(static_cast<int32_t>(GetEntryCount()));
-
last_committed_entry_index_ = selected_index;
}
@@ -2093,16 +2041,6 @@ void NavigationControllerImpl::DiscardTransientEntry() {
transient_entry_index_ = -1;
}
-int NavigationControllerImpl::GetEntryIndexWithPageID(SiteInstance* instance,
- int32_t page_id) const {
- for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
- if ((entries_[i]->site_instance() == instance) &&
- (entries_[i]->GetPageID() == page_id))
- return i;
- }
- return -1;
-}
-
int NavigationControllerImpl::GetEntryIndexWithUniqueID(
int nav_entry_id) const {
for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) {
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 527fb8feb50..bbba71b943f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -77,8 +77,6 @@ class CONTENT_EXPORT NavigationControllerImpl
const SessionStorageNamespaceMap& GetSessionStorageNamespaceMap()
const override;
SessionStorageNamespace* GetDefaultSessionStorageNamespace() override;
- void SetMaxRestoredPageID(int32_t max_id) override;
- int32_t GetMaxRestoredPageID() const override;
bool NeedsReload() const override;
void SetNeedsReload() override;
void CancelPendingReload() override;
@@ -111,18 +109,9 @@ class CONTENT_EXPORT NavigationControllerImpl
// in this NavigationController.
int GetIndexOfEntry(const NavigationEntryImpl* entry) const;
- // Return the index of the entry with the corresponding instance and page_id,
- // or -1 if not found.
- int GetEntryIndexWithPageID(SiteInstance* instance, int32_t page_id) const;
-
// Return the index of the entry with the given unique id, or -1 if not found.
int GetEntryIndexWithUniqueID(int nav_entry_id) const;
- // Return the entry with the corresponding instance and page_id, or null if
- // not found.
- NavigationEntryImpl* GetEntryWithPageID(SiteInstance* instance,
- int32_t page_id) const;
-
// Return the entry with the given unique id, or null if not found.
NavigationEntryImpl* GetEntryWithUniqueID(int nav_entry_id) const;
@@ -150,7 +139,8 @@ class CONTENT_EXPORT NavigationControllerImpl
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
LoadCommittedDetails* details,
- bool is_navigation_within_page);
+ bool is_navigation_within_page,
+ NavigationHandleImpl* navigation_handle);
// Notifies us that we just became active. This is used by the WebContentsImpl
// so that we know to load URLs that were pending as "lazy" loads.
@@ -287,14 +277,17 @@ class CONTENT_EXPORT NavigationControllerImpl
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
bool is_in_page,
- bool replace_entry);
+ bool replace_entry,
+ NavigationHandleImpl* handle);
void RendererDidNavigateToExistingPage(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
- bool is_in_page);
+ bool is_in_page,
+ NavigationHandleImpl* handle);
void RendererDidNavigateToSamePage(
RenderFrameHostImpl* rfh,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ NavigationHandleImpl* handle);
void RendererDidNavigateNewSubframe(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
@@ -405,11 +398,6 @@ class CONTENT_EXPORT NavigationControllerImpl
// setup.
NavigationControllerDelegate* delegate_;
- // The max restored page ID in this controller, if it was restored. We must
- // store this so that WebContentsImpl can tell any renderer in charge of one
- // of the restored entries to update its max page ID.
- int32_t max_restored_page_id_;
-
// Manages the SSL security UI.
SSLManager ssl_manager_;
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 e539e20b660..36b684d9700 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -5,14 +5,20 @@
#include "content/browser/frame_host/navigation_controller_impl.h"
#include <stdint.h>
+#include <algorithm>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "content/browser/frame_host/frame_navigation_entry.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
@@ -21,6 +27,7 @@
#include "content/common/frame_messages.h"
#include "content/common/page_state_serialization.h"
#include "content/common/site_isolation_policy.h"
+#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_controller.h"
@@ -42,9 +49,9 @@
#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/content_browser_test_utils_internal.h"
-#include "content/test/test_frame_navigation_observer.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/url_request/url_request_failed_job.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
@@ -69,8 +76,8 @@ class NavigationControllerBrowserTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
};
@@ -570,48 +577,6 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// will have to suffice.
}
-// Check that we will not trigger a DCHECK in renderer for cross-process
-// replacement navigations.
-// See https://crbug.com/611679.
-IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
- PageIDUpdatedOnPageReplacement) {
- NavigationController& controller = shell()->web_contents()->GetController();
- const GURL page_url = embedded_test_server()->GetURL(
- "/navigation_controller/simple_page_1.html");
-
- // Use a chrome:// url first so that the next page will be loaded
- // in a separate site instance.
- GURL initial_url(std::string(kChromeUIScheme) +
- url::kStandardSchemeSeparator + kChromeUIGpuHost);
- EXPECT_TRUE(NavigateToURL(shell(), initial_url));
- EXPECT_EQ(1, controller.GetEntryCount());
- EXPECT_NE(-1, shell()->web_contents()->GetMaxPageID());
- int initial_renderer_id =
- shell()->web_contents()->GetRenderProcessHost()->GetID();
-
- // Now navigate and replace the current entry.
- RendererLocationReplace(shell(), page_url);
-
- // Verify that process swap actually occured.
- EXPECT_NE(initial_renderer_id,
- shell()->web_contents()->GetRenderProcessHost()->GetID());
-
- // The navigation entry should have been replaced.
- EXPECT_EQ(1, controller.GetEntryCount());
-
- // Page ID should be updated.
- EXPECT_NE(-1, shell()->web_contents()->GetMaxPageID());
-
- // Reload the page and verify that we don't hit
- // a DCHECK in |RenderFrameImpl::NavigateInternal|.
- controller.Reload(false);
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-
- // DCHECK shouldn't be triggered and we should have a valid page ID.
- EXPECT_NE(-1, shell()->web_contents()->GetMaxPageID());
- EXPECT_TRUE(shell()->web_contents()->GetMainFrame()->IsRenderFrameLive());
-}
-
namespace {
class NoNavigationsObserver : public WebContentsObserver {
@@ -1898,7 +1863,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"document.body.appendChild(iframe);";
EXPECT_TRUE(ExecuteScript(root, script));
}
- EXPECT_TRUE(subframe_delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(subframe_delayer.WaitForRequestStart());
// Stop the request so that we can wait for load stop below, without ending up
// with a commit for this frame.
@@ -2272,15 +2237,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the tree of FrameNavigationEntries after NAVIGATION_TYPE_NEW_SUBFRAME
// commits.
-// Disabled due to flakes on Linux Tests; see https://crbug.com/646836.
-#if defined(OS_LINUX)
-#define MAYBE_FrameNavigationEntry_NewSubframe \
- DISABLED_FrameNavigationEntry_NewSubframe
-#else
-#define MAYBE_FrameNavigationEntry_NewSubframe FrameNavigationEntry_NewSubframe
-#endif
+// Disabled due to flakes; see https://crbug.com/646836.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
- MAYBE_FrameNavigationEntry_NewSubframe) {
+ FrameNavigationEntry_NewSubframe) {
GURL main_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2348,7 +2307,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
// 4. Create a nested same-site iframe in the second subframe, wait for it to
- // commit, then navigate it again.
+ // commit, then navigate it again cross-site.
{
LoadCommittedCapturer capturer(shell()->web_contents());
std::string script = "var iframe = document.createElement('iframe');"
@@ -2361,7 +2320,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"bar.com", "/navigation_controller/simple_page_1.html"));
{
FrameNavigateParamsCapturer capturer(root->child_at(1)->child_at(0));
+ RenderFrameDeletedObserver deleted_observer(
+ root->child_at(1)->child_at(0)->current_frame_host());
NavigateFrameToURL(root->child_at(1)->child_at(0), bar_url);
+ // Wait for the RenderFrame to go away, if this will be cross-process.
+ if (AreAllSitesIsolatedForTesting())
+ deleted_observer.WaitUntilDeleted();
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -2397,9 +2361,14 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"baz.com", "/navigation_controller/simple_page_1.html"));
{
FrameNavigateParamsCapturer capturer(root->child_at(1));
+ RenderFrameDeletedObserver deleted_observer(
+ root->child_at(1)->current_frame_host());
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[1].src = '" + baz_url.spec() + "';";
EXPECT_TRUE(ExecuteScript(root, script));
+ // Wait for the RenderFrame to go away, if this will be cross-process.
+ if (AreAllSitesIsolatedForTesting())
+ deleted_observer.WaitUntilDeleted();
capturer.Wait();
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -3940,7 +3909,6 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigationControllerImpl::CreateNavigationEntry(
main_url_a, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), controller.GetBrowserContext()));
- restored_entry->SetPageID(0);
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
restored_entry->SetPageState(entry2->GetPageState());
@@ -4023,7 +3991,6 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigationControllerImpl::CreateNavigationEntry(
main_url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), controller.GetBrowserContext()));
- restored_entry->SetPageID(0);
restored_entry->SetPageState(PageState::CreateFromURL(main_url));
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
@@ -4599,7 +4566,6 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerOopifBrowserTest,
NavigationControllerImpl::CreateNavigationEntry(
main_url_a, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), controller.GetBrowserContext()));
- restored_entry->SetPageID(0);
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
restored_entry->SetPageState(entry2->GetPageState());
@@ -4815,7 +4781,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// second page, though, causes it to do a replaceState().
TestNavigationManager manager(shell()->web_contents(), start_url);
controller.GoBack();
- EXPECT_TRUE(manager.WaitForWillStartRequest());
+ EXPECT_TRUE(manager.WaitForRequestStart());
// The navigation that just happened was the replaceState(), which should not
// have changed the position into the navigation entry list. Make sure that
@@ -5738,9 +5704,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
frame_url_a2);
TestNavigationManager mainframe_delayer(shell()->web_contents(), url_b);
controller.GoForward();
- EXPECT_TRUE(subframe_delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(subframe_delayer.WaitForRequestStart());
controller.GoForward();
- EXPECT_TRUE(mainframe_delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(mainframe_delayer.WaitForRequestStart());
EXPECT_EQ(2, controller.GetPendingEntryIndex());
// Let the subframe commit.
@@ -5783,7 +5749,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationManager delayer(shell()->web_contents(),
embedded_test_server()->GetURL("/title3.html"));
shell()->LoadURL(embedded_test_server()->GetURL("/title3.html"));
- EXPECT_TRUE(delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(delayer.WaitForRequestStart());
NavigationController& controller = shell()->web_contents()->GetController();
@@ -6796,4 +6762,276 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
histogram.ExpectTotalCount(kReloadMainResourceToReloadMetricName, 3);
}
+// Check that the referrer is stored inside FrameNavigationEntry for subframes.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ RefererStoredForSubFrame) {
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
+ return;
+
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ GURL url_simple(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_iframe_simple.html"));
+ GURL url_redirect(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_iframe_redirect.html"));
+
+ // Run this test twice: with and without a redirection.
+ for (const GURL& url : {url_simple, url_redirect}) {
+ // Navigate to a page with an iframe.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ // Check the FrameNavigationEntry's referrer.
+ NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+ ASSERT_EQ(1U, entry->root_node()->children.size());
+ FrameNavigationEntry* frame_entry =
+ entry->root_node()->children[0]->frame_entry.get();
+ EXPECT_EQ(frame_entry->referrer().url, url);
+ }
+}
+
+namespace {
+
+class RequestMonitoringNavigationBrowserTest : public ContentBrowserTest {
+ public:
+ RequestMonitoringNavigationBrowserTest() : weak_factory_(this) {}
+
+ const net::test_server::HttpRequest* FindAccumulatedRequest(
+ const GURL& url_to_find) {
+ // net::test_server::HttpRequest::GetURL hardcodes "http://localhost/" part.
+ GURL::Replacements replacements;
+ replacements.SetHostStr("localhost");
+ replacements.ClearPort();
+ replacements.SetSchemeStr("http");
+ DCHECK(url_to_find.SchemeIsHTTPOrHTTPS());
+ GURL canonical_url_to_find = url_to_find.ReplaceComponents(replacements);
+
+ auto it = std::find_if(
+ accumulated_requests_.begin(), accumulated_requests_.end(),
+ [&canonical_url_to_find](const net::test_server::HttpRequest& request) {
+ return request.GetURL() == canonical_url_to_find;
+ });
+ if (it == accumulated_requests_.end())
+ return nullptr;
+ return &*it;
+ }
+
+ protected:
+ void SetUpOnMainThread() override {
+ // Accumulate all http requests made to |embedded_test_server| into
+ // |accumulated_requests_| container.
+ embedded_test_server()->RegisterRequestMonitor(base::Bind(
+ &RequestMonitoringNavigationBrowserTest::MonitorRequestOnIoThread,
+ weak_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get()));
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ void TearDown() override {
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+ }
+
+ private:
+ static void MonitorRequestOnIoThread(
+ const base::WeakPtr<RequestMonitoringNavigationBrowserTest>& weak_this,
+ const scoped_refptr<base::SequencedTaskRunner>& postback_task_runner,
+ const net::test_server::HttpRequest& request) {
+ postback_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &RequestMonitoringNavigationBrowserTest::MonitorRequestOnMainThread,
+ weak_this, request));
+ }
+
+ void MonitorRequestOnMainThread(
+ const net::test_server::HttpRequest& request) {
+ accumulated_requests_.push_back(request);
+ }
+
+ std::vector<net::test_server::HttpRequest> accumulated_requests_;
+ base::WeakPtrFactory<RequestMonitoringNavigationBrowserTest> weak_factory_;
+};
+
+// Helper for waiting until the main frame of |web_contents| has loaded
+// |expected_url| (and all subresources have finished loading).
+class WebContentsLoadFinishedWaiter : public WebContentsObserver {
+ public:
+ WebContentsLoadFinishedWaiter(WebContents* web_contents,
+ const GURL& expected_url)
+ : WebContentsObserver(web_contents),
+ expected_url_(expected_url),
+ message_loop_runner_(new MessageLoopRunner) {
+ EXPECT_TRUE(web_contents != NULL);
+ }
+
+ void Wait() { message_loop_runner_->Run(); }
+
+ private:
+ void DidFinishLoad(RenderFrameHost* render_frame_host,
+ const GURL& url) override {
+ bool is_main_frame = !render_frame_host->GetParent();
+ if (url == expected_url_ && is_main_frame)
+ message_loop_runner_->Quit();
+ }
+
+ GURL expected_url_;
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+};
+
+} // namespace {
+
+// Check that NavigationController::LoadURLParams::extra_headers are not copied
+// to subresource requests.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringNavigationBrowserTest,
+ ExtraHeadersVsSubresources) {
+ GURL page_url = embedded_test_server()->GetURL("/page_with_image.html");
+ GURL image_url = embedded_test_server()->GetURL("/blank.jpg");
+
+ // Navigate via LoadURLWithParams (setting |extra_headers| field).
+ WebContentsLoadFinishedWaiter waiter(shell()->web_contents(), page_url);
+ NavigationController::LoadURLParams load_url_params(page_url);
+ load_url_params.extra_headers = "X-ExtraHeadersVsSubresources: 1";
+ shell()->web_contents()->GetController().LoadURLWithParams(load_url_params);
+ waiter.Wait();
+ EXPECT_EQ(page_url, shell()->web_contents()->GetLastCommittedURL());
+
+ // Verify that the extra header was present for the page.
+ const net::test_server::HttpRequest* page_request =
+ FindAccumulatedRequest(page_url);
+ ASSERT_TRUE(page_request);
+ EXPECT_THAT(page_request->headers,
+ testing::Contains(testing::Key("X-ExtraHeadersVsSubresources")));
+
+ // Verify that the extra header was NOT present for the subresource.
+ const net::test_server::HttpRequest* image_request =
+ FindAccumulatedRequest(image_url);
+ ASSERT_TRUE(image_request);
+ EXPECT_THAT(image_request->headers,
+ testing::Not(testing::Contains(
+ testing::Key("X-ExtraHeadersVsSubresources"))));
+}
+
+class NavigationHandleCommitObserver : public WebContentsObserver {
+ public:
+ NavigationHandleCommitObserver(WebContents* web_contents, const GURL& url)
+ : WebContentsObserver(web_contents),
+ url_(url),
+ has_committed_(false),
+ was_same_page_(false),
+ was_renderer_initiated_(false) {}
+
+ bool has_committed() const { return has_committed_; }
+ bool was_same_page() const { return was_same_page_; }
+ bool was_renderer_initiated() const { return was_renderer_initiated_; }
+
+ private:
+ void DidFinishNavigation(NavigationHandle* handle) override {
+ if (handle->GetURL() != url_)
+ return;
+ has_committed_ = true;
+ was_same_page_ = handle->IsSamePage();
+ was_renderer_initiated_ = handle->IsRendererInitiated();
+ }
+
+ const GURL url_;
+ bool has_committed_;
+ bool was_same_page_;
+ bool was_renderer_initiated_;
+};
+
+// Test that a same-page navigation does not lead to the deletion of the
+// NavigationHandle for an ongoing different page navigation.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ SamePageNavigationDoesntDeleteNavigationHandle) {
+ const GURL kURL1 = embedded_test_server()->GetURL("/title1.html");
+ const GURL kPushStateURL =
+ embedded_test_server()->GetURL("/title1.html#fragment");
+ const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
+
+ // Navigate to the initial page.
+ EXPECT_TRUE(NavigateToURL(shell(), kURL1));
+ RenderFrameHostImpl* main_frame =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->GetMainFrame();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_FALSE(main_frame->navigation_handle());
+ EXPECT_FALSE(root->navigation_request());
+
+ // Start navigating to the second page.
+ TestNavigationManager manager(shell()->web_contents(), kURL2);
+ NavigationHandleCommitObserver navigation_observer(shell()->web_contents(),
+ kURL2);
+ shell()->web_contents()->GetController().LoadURL(
+ kURL2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ EXPECT_TRUE(manager.WaitForRequestStart());
+
+ // This should create a NavigationHandle.
+ NavigationHandleImpl* handle = main_frame->navigation_handle();
+ NavigationRequest* request = root->navigation_request();
+ if (IsBrowserSideNavigationEnabled()) {
+ EXPECT_TRUE(request);
+ } else {
+ EXPECT_TRUE(handle);
+ }
+
+ // The current page does a PushState.
+ NavigationHandleCommitObserver push_state_observer(shell()->web_contents(),
+ kPushStateURL);
+ std::string push_state =
+ "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");";
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), push_state));
+ NavigationEntry* last_committed =
+ shell()->web_contents()->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(last_committed);
+ EXPECT_EQ(kPushStateURL, last_committed->GetURL());
+
+ EXPECT_TRUE(push_state_observer.has_committed());
+ EXPECT_TRUE(push_state_observer.was_same_page());
+ EXPECT_TRUE(push_state_observer.was_renderer_initiated());
+
+ // This shouldn't affect the ongoing navigation.
+ if (IsBrowserSideNavigationEnabled()) {
+ EXPECT_TRUE(root->navigation_request());
+ EXPECT_EQ(request, root->navigation_request());
+ } else {
+ EXPECT_TRUE(main_frame->navigation_handle());
+ EXPECT_EQ(handle, main_frame->navigation_handle());
+ }
+
+ // Let the navigation finish. It should commit successfully.
+ manager.WaitForNavigationFinished();
+ last_committed =
+ shell()->web_contents()->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(last_committed);
+ EXPECT_EQ(kURL2, last_committed->GetURL());
+
+ EXPECT_TRUE(navigation_observer.has_committed());
+ EXPECT_FALSE(navigation_observer.was_same_page());
+ EXPECT_FALSE(navigation_observer.was_renderer_initiated());
+
+}
+
+// Tests that a same-page browser-initiated navigation is properly reported by
+// the NavigationHandle.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ SamePageBrowserInitiated) {
+ const GURL kURL = embedded_test_server()->GetURL("/title1.html");
+ const GURL kFragmentURL =
+ embedded_test_server()->GetURL("/title1.html#fragment");
+
+ // Navigate to the initial page.
+ EXPECT_TRUE(NavigateToURL(shell(), kURL));
+
+ // Do a browser-initiated fragment navigation.
+ NavigationHandleCommitObserver handle_observer(shell()->web_contents(),
+ kFragmentURL);
+ EXPECT_TRUE(NavigateToURL(shell(), kFragmentURL));
+
+ EXPECT_TRUE(handle_observer.has_committed());
+ EXPECT_TRUE(handle_observer.was_same_page());
+ EXPECT_FALSE(handle_observer.was_renderer_initiated());
+}
+
} // 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 44b7ff82a28..9086801514f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -20,7 +20,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/frame_navigation_entry.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
@@ -363,7 +362,7 @@ TEST_F(NavigationControllerTest, GoToOffset) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(urls[0], true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, 0, true, urls[0]);
+ main_test_rfh()->SendNavigate(0, true, urls[0]);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(urls[0], controller.GetVisibleEntry()->GetVirtualURL());
@@ -374,7 +373,7 @@ TEST_F(NavigationControllerTest, GoToOffset) {
for (int i = 1; i <= 4; ++i) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(urls[i], true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(i, 0, true, urls[i]);
+ main_test_rfh()->SendNavigate(0, true, urls[i]);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(urls[i], controller.GetVisibleEntry()->GetVirtualURL());
@@ -411,7 +410,7 @@ TEST_F(NavigationControllerTest, GoToOffset) {
// Check that the GoToOffset will land on the expected page.
EXPECT_EQ(urls[url_index], controller.GetPendingEntry()->GetVirtualURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(url_index, entry_id, false, urls[url_index]);
+ main_test_rfh()->SendNavigate(entry_id, false, urls[url_index]);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Check that we can go to any valid offset into the history.
@@ -545,7 +544,6 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(controller.GetPendingEntry(), controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(contents()->GetMaxPageID(), -1);
// Neither the timestamp nor the status code should have been set yet.
EXPECT_TRUE(controller.GetPendingEntry()->GetTimestamp().is_null());
@@ -555,7 +553,7 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -568,7 +566,6 @@ TEST_F(NavigationControllerTest, LoadURL) {
ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(contents()->GetMaxPageID(), 0);
EXPECT_EQ(0, controller.GetLastCommittedEntry()->bindings());
// The timestamp should have been set.
@@ -589,14 +586,13 @@ TEST_F(NavigationControllerTest, LoadURL) {
// TODO(darin): maybe this should really be true?
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(contents()->GetMaxPageID(), 0);
EXPECT_TRUE(controller.GetPendingEntry()->GetTimestamp().is_null());
// Simulate the beforeunload ack for the cross-site transition, and then the
// commit.
main_test_rfh()->PrepareForCommit();
- contents()->GetPendingMainFrame()->SendNavigate(1, entry_id, true, url2);
+ contents()->GetPendingMainFrame()->SendNavigate(entry_id, true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -609,7 +605,6 @@ TEST_F(NavigationControllerTest, LoadURL) {
ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(contents()->GetMaxPageID(), 1);
EXPECT_FALSE(controller.GetVisibleEntry()->GetTimestamp().is_null());
}
@@ -639,7 +634,7 @@ TEST_F(NavigationControllerTest, LoadURLSameTime) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -651,7 +646,7 @@ TEST_F(NavigationControllerTest, LoadURLSameTime) {
// Simulate the beforeunload ack for the cross-site transition, and then the
// commit.
main_test_rfh()->PrepareForCommit();
- contents()->GetPendingMainFrame()->SendNavigate(1, entry_id, true, url2);
+ contents()->GetPendingMainFrame()->SendNavigate(entry_id, true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -793,7 +788,7 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
- 0, entry_id, true, url1, ui::PAGE_TRANSITION_TYPED);
+ entry_id, true, url1, ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -808,7 +803,7 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
- 0, entry_id, false, url1, ui::PAGE_TRANSITION_TYPED);
+ entry_id, false, url1, ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -844,7 +839,6 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = controller.GetPendingEntry()->GetUniqueID();
params.did_create_new_entry = true;
params.url = url1;
@@ -865,7 +859,7 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
- 0, controller.GetPendingEntry()->GetUniqueID(),
+ controller.GetPendingEntry()->GetUniqueID(),
false, url1, ui::PAGE_TRANSITION_TYPED);
// We should not have produced a new session history entry.
@@ -890,7 +884,7 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -930,13 +924,13 @@ TEST_F(NavigationControllerTest, LoadURL_NoPending) {
kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Do a new navigation without making a pending one.
const GURL kNewURL("http://see");
- main_test_rfh()->NavigateAndCommitRendererInitiated(99, true, kNewURL);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kNewURL);
// There should no longer be any pending entry, and the second navigation we
// just made should be committed.
@@ -962,7 +956,7 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -979,7 +973,7 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
const GURL kNewURL("http://see");
main_test_rfh()->SendRendererInitiatedNavigationRequest(kNewURL, true);
main_test_rfh()->PrepareForCommit();
- contents()->GetMainFrame()->SendNavigate(3, 0, true, kNewURL);
+ contents()->GetMainFrame()->SendNavigate(0, true, kNewURL);
// There should no longer be any pending entry, and the third navigation we
// just made should be committed.
@@ -1004,7 +998,7 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1013,7 +1007,7 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL2);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1028,7 +1022,7 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
const GURL kNewURL("http://foo/see");
main_test_rfh()->SendRendererInitiatedNavigationRequest(kNewURL, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, 0, true, kNewURL);
+ main_test_rfh()->SendNavigate(0, true, kNewURL);
// There should no longer be any pending entry, and the new navigation we
// just made should be committed.
@@ -1055,7 +1049,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// Pretend it has bindings so we can tell if we incorrectly copy it.
main_test_rfh()->GetRenderViewHost()->AllowBindings(2);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1066,7 +1060,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
TestRenderFrameHost* foo_rfh = contents()->GetPendingMainFrame();
- foo_rfh->SendNavigate(1, entry_id, true, kExistingURL2);
+ foo_rfh->SendNavigate(entry_id, true, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1083,7 +1077,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
const GURL kNewURL("http://foo/bee");
foo_rfh->SendRendererInitiatedNavigationRequest(kNewURL, true);
foo_rfh->PrepareForCommit();
- foo_rfh->SendNavigate(3, 0, true, kNewURL);
+ foo_rfh->SendNavigate(0, true, kNewURL);
// There should no longer be any pending entry, and the new navigation we
// just made should be committed.
@@ -1109,7 +1103,7 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1118,7 +1112,7 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL2);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1136,7 +1130,7 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
// ...and the back navigation commits.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, false, kExistingURL1);
+ main_test_rfh()->SendNavigate(entry_id, false, kExistingURL1);
// There should no longer be any pending entry, and the back navigation should
// be committed.
@@ -1175,10 +1169,10 @@ TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
EXPECT_EQ(1, delegate->navigation_state_change_count());
// Before that commits, a document.write and location.reload can cause the
- // renderer to send a FrameNavigate with page_id -1 and nav_entry_id 0.
+ // renderer to send a FrameNavigate with nav_entry_id 0.
// PlzNavigate: this will stop the old navigation and start a new one.
main_test_rfh()->SendRendererInitiatedNavigationRequest(kExistingURL, true);
- main_test_rfh()->SendNavigate(-1, 0, false, kExistingURL);
+ main_test_rfh()->SendNavigate(0, false, kExistingURL);
// This should clear the pending entry and notify of a navigation state
// change, so that we do not keep displaying kNewURL.
@@ -1257,7 +1251,7 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL);
+ main_test_rfh()->SendNavigate(entry_id, true, kExistingURL);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1326,7 +1320,7 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
// Commit.
TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
orig_rfh->PrepareForCommit();
- orig_rfh->SendNavigate(0, entry1_id, true, url1);
+ orig_rfh->SendNavigate(entry1_id, true, url1);
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(0, controller.GetLastCommittedEntry()->bindings());
@@ -1347,7 +1341,7 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
orig_rfh->PrepareForCommit();
TestRenderFrameHost* new_rfh = contents()->GetPendingMainFrame();
new_rfh->GetRenderViewHost()->AllowBindings(1);
- new_rfh->SendNavigate(1, entry_id, true, url2);
+ new_rfh->SendNavigate(entry_id, true, url2);
// The second load should be committed, and bindings should be remembered.
EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1358,7 +1352,7 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
// Going back, the first entry should still appear unprivileged.
controller.GoBack();
new_rfh->PrepareForCommit();
- contents()->GetPendingMainFrame()->SendNavigate(0, entry1_id, false, url1);
+ contents()->GetPendingMainFrame()->SendNavigate(entry1_id, false, url1);
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(0, controller.GetLastCommittedEntry()->bindings());
}
@@ -1375,7 +1369,7 @@ TEST_F(NavigationControllerTest, Reload) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
ASSERT_TRUE(controller.GetVisibleEntry());
@@ -1402,7 +1396,7 @@ TEST_F(NavigationControllerTest, Reload) {
EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, false, url1);
+ main_test_rfh()->SendNavigate(entry_id, false, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1433,7 +1427,7 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
@@ -1442,7 +1436,7 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommitWithServerRedirect(url2);
- main_test_rfh()->SendNavigate(1, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1467,7 +1461,7 @@ TEST_F(NavigationControllerTest, ReloadWithGuest) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
ASSERT_TRUE(controller.GetVisibleEntry());
// Make the entry believe its RenderProcessHost is a guest.
@@ -1512,7 +1506,7 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->PrepareForCommitWithServerRedirect(final_url);
main_test_rfh()->SendNavigateWithModificationCallback(
- 0, entry_id, true, final_url, set_original_url_callback);
+ entry_id, true, final_url, set_original_url_callback);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
@@ -1545,7 +1539,7 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
// Send that the navigation has proceeded; say it got redirected again.
main_test_rfh()->PrepareForCommitWithServerRedirect(final_url);
- main_test_rfh()->SendNavigate(0, entry_id, false, final_url);
+ main_test_rfh()->SendNavigate(entry_id, false, final_url);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1573,7 +1567,7 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url0);
+ main_test_rfh()->SendNavigate(entry_id, true, url0);
// Set up the pending entry.
const GURL url1("http://foo/1");
@@ -1602,7 +1596,7 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
// Fake a commit response.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigateWithReplacement(1, entry_id, true, url1);
+ main_test_rfh()->SendNavigateWithReplacement(entry_id, true, url1);
// Certain values that are only used for pending entries get reset after
// commit.
@@ -1644,7 +1638,7 @@ TEST_F(NavigationControllerTest, RedirectsAreNotResetByCommit) {
// Normal navigation will preserve redirects in the committed entry.
main_test_rfh()->PrepareForCommitWithServerRedirect(url2);
- main_test_rfh()->SendNavigateWithModificationCallback(0, entry_id, true, url1,
+ main_test_rfh()->SendNavigateWithModificationCallback(entry_id, true, url1,
set_redirects_callback);
NavigationEntryImpl* committed_entry = controller.GetLastCommittedEntry();
ASSERT_EQ(1U, committed_entry->GetRedirectChain().size());
@@ -1658,12 +1652,12 @@ TEST_F(NavigationControllerTest, Back) {
RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
const GURL url2("http://foo2");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1689,7 +1683,7 @@ TEST_F(NavigationControllerTest, Back) {
controller.GetEntryAtIndex(0)->GetTimestamp());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, false, url2);
+ main_test_rfh()->SendNavigate(entry_id, false, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1725,7 +1719,7 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry1_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry1_id, true, url1);
+ main_test_rfh()->SendNavigate(entry1_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
entry1_id = controller.GetLastCommittedEntry()->GetUniqueID();
@@ -1734,7 +1728,7 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1751,7 +1745,7 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
EXPECT_TRUE(controller.CanGoForward());
main_test_rfh()->PrepareForCommitWithServerRedirect(url3);
- main_test_rfh()->SendNavigate(2, entry1_id, true, url3);
+ main_test_rfh()->SendNavigate(entry1_id, true, url3);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1777,12 +1771,12 @@ TEST_F(NavigationControllerTest, Back_NewPending) {
const GURL kUrl3("http://foo3");
// First navigate two places so we have some back history.
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, kUrl1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// controller.LoadURL(kUrl2, ui::PAGE_TRANSITION_TYPED);
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, kUrl2);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1810,21 +1804,21 @@ TEST_F(NavigationControllerTest, Forward) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, 0, true, url1);
+ main_test_rfh()->SendNavigate(0, true, url1);
NavigationEntry* entry1 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, 0, true, url2);
+ main_test_rfh()->SendNavigate(0, true, url2);
NavigationEntry* entry2 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
controller.GoBack();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry1->GetUniqueID(), false, url1);
+ main_test_rfh()->SendNavigate(entry1->GetUniqueID(), false, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1849,7 +1843,7 @@ TEST_F(NavigationControllerTest, Forward) {
controller.GetEntryAtIndex(1)->GetTimestamp());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry2->GetUniqueID(), false, url2);
+ main_test_rfh()->SendNavigate(entry2->GetUniqueID(), false, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1883,20 +1877,20 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, 0, true, url1);
+ main_test_rfh()->SendNavigate(0, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
NavigationEntry* entry1 = controller.GetLastCommittedEntry();
navigation_entry_committed_counter_ = 0;
main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, 0, true, url2);
+ main_test_rfh()->SendNavigate(0, true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
NavigationEntry* entry2 = controller.GetLastCommittedEntry();
navigation_entry_committed_counter_ = 0;
controller.GoBack();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry1->GetUniqueID(), false, url1);
+ main_test_rfh()->SendNavigate(entry1->GetUniqueID(), false, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1913,7 +1907,7 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
EXPECT_FALSE(controller.CanGoForward());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry2->GetUniqueID(), true, url3);
+ 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));
@@ -1945,7 +1939,6 @@ TEST_F(NavigationControllerTest, Redirect) {
EXPECT_EQ(0U, notifications.size());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = entry_id;
params.did_create_new_entry = true;
params.url = url2;
@@ -2013,7 +2006,6 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
EXPECT_EQ(0U, notifications.size());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = entry_id;
params.did_create_new_entry = true;
params.url = url2;
@@ -2082,7 +2074,6 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = entry_id;
params.did_create_new_entry = true;
params.url = url2;
@@ -2135,7 +2126,7 @@ TEST_F(NavigationControllerTest,
const GURL url2("http://foo2");
// Start with a loaded page.
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(nullptr, controller_impl().GetPendingEntry());
// Start a load of the same page again.
@@ -2151,7 +2142,6 @@ TEST_F(NavigationControllerTest,
// ... and now the renderer sends a commit for the first navigation.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = entry_id1;
params.intended_as_new_entry = true;
params.did_create_new_entry = false;
@@ -2174,7 +2164,7 @@ TEST_F(NavigationControllerTest, NewSubframe) {
RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2189,7 +2179,6 @@ TEST_F(NavigationControllerTest, NewSubframe) {
const GURL subframe_url("http://foo1/subframe");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -2216,7 +2205,6 @@ TEST_F(NavigationControllerTest, NewSubframe) {
// Now do a new navigation in the frame.
const GURL url2("http://foo2");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 2;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = true;
@@ -2245,7 +2233,6 @@ TEST_F(NavigationControllerTest, NewSubframe) {
// New entry should refer to the new page, but the old URL (entries only
// reflect the toplevel URL).
EXPECT_EQ(url1, entry->GetURL());
- EXPECT_EQ(params.page_id, entry->GetPageID());
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
@@ -2267,7 +2254,7 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo/1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2282,7 +2269,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
const GURL url2("http://foo/2");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name0;
params.did_create_new_entry = false;
@@ -2310,7 +2296,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
EXPECT_EQ(1, controller.GetEntryCount());
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
EXPECT_EQ(url1, entry->GetURL());
- EXPECT_EQ(1, entry->GetPageID());
FrameNavigationEntry* root_entry = entry->root_node()->frame_entry.get();
EXPECT_EQ(url1, root_entry->url());
@@ -2337,7 +2322,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
const GURL url3("http://foo/3");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name1;
params.did_create_new_entry = false;
@@ -2365,7 +2349,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(entry, controller.GetLastCommittedEntry());
EXPECT_EQ(url1, entry->GetURL());
- EXPECT_EQ(1, entry->GetPageID());
EXPECT_EQ(root_entry, entry->root_node()->frame_entry.get());
EXPECT_EQ(url1, root_entry->url());
@@ -2397,7 +2380,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
const GURL url4("http://foo/4");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name2;
params.did_create_new_entry = false;
@@ -2425,7 +2407,6 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(entry, controller.GetLastCommittedEntry());
EXPECT_EQ(url1, entry->GetURL());
- EXPECT_EQ(1, entry->GetPageID());
EXPECT_EQ(root_entry, entry->root_node()->frame_entry.get());
EXPECT_EQ(url1, root_entry->url());
@@ -2451,7 +2432,7 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Main page.
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
NavigationEntry* entry1 = controller.GetLastCommittedEntry();
navigation_entry_committed_counter_ = 0;
@@ -2472,7 +2453,6 @@ TEST_F(NavigationControllerTest, BackSubframe) {
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -2504,7 +2484,6 @@ TEST_F(NavigationControllerTest, BackSubframe) {
int64_t item_sequence_number2 = GenerateSequenceNumber();
int64_t document_sequence_number2 = GenerateSequenceNumber();
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 2;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = true;
@@ -2542,7 +2521,6 @@ TEST_F(NavigationControllerTest, BackSubframe) {
const GURL url3("http://foo3");
int64_t item_sequence_number3 = GenerateSequenceNumber();
int64_t document_sequence_number3 = GenerateSequenceNumber();
- params.page_id = 3;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = true;
@@ -2573,7 +2551,6 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Go back one.
controller.GoBack();
- params.page_id = 2;
params.nav_entry_id = entry2->GetUniqueID();
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -2595,7 +2572,6 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Go back one more.
controller.GoBack();
- params.page_id = 1;
params.nav_entry_id = entry1->GetUniqueID();
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -2624,11 +2600,11 @@ TEST_F(NavigationControllerTest, LinkClick) {
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2649,14 +2625,13 @@ TEST_F(NavigationControllerTest, InPage) {
// Main page.
const GURL url1("http://foo");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Ensure main page navigation to same url respects the was_within_same_page
// hint provided in the params.
FrameHostMsg_DidCommitProvisionalLoad_Params self_params;
- self_params.page_id = 0;
self_params.nav_entry_id = 0;
self_params.did_create_new_entry = false;
self_params.url = url1;
@@ -2678,10 +2653,9 @@ TEST_F(NavigationControllerTest, InPage) {
EXPECT_TRUE(observer.details().did_replace_entry);
EXPECT_EQ(1, controller.GetEntryCount());
- // Fragment navigation to a new page_id.
+ // Fragment navigation to a new page.
const GURL url2("http://foo#a");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url2;
@@ -2707,7 +2681,6 @@ TEST_F(NavigationControllerTest, InPage) {
FrameHostMsg_DidCommitProvisionalLoad_Params back_params(params);
controller.GoBack();
back_params.url = url1;
- back_params.page_id = 0;
back_params.nav_entry_id = entry1->GetUniqueID();
back_params.did_create_new_entry = false;
main_test_rfh()->PrepareForCommit();
@@ -2723,7 +2696,6 @@ TEST_F(NavigationControllerTest, InPage) {
FrameHostMsg_DidCommitProvisionalLoad_Params forward_params(params);
controller.GoForward();
forward_params.url = url2;
- forward_params.page_id = 1;
forward_params.nav_entry_id = entry2->GetUniqueID();
forward_params.did_create_new_entry = false;
main_test_rfh()->PrepareForCommit();
@@ -2751,7 +2723,6 @@ TEST_F(NavigationControllerTest, InPage) {
// Finally, navigate to an unrelated URL to make sure in_page is not sticky.
const GURL url3("http://bar");
- params.page_id = 2;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url3;
@@ -2773,14 +2744,13 @@ TEST_F(NavigationControllerTest, InPage_Replace) {
// Main page.
const GURL url1("http://foo");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// First navigation.
const GURL url2("http://foo#a");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0; // Same page_id
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.url = url2;
@@ -2817,7 +2787,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
// Load an initial page.
{
const GURL url("http://foo/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
}
@@ -2825,7 +2795,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
// Navigate to a new page.
{
const GURL url("http://foo2/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
}
@@ -2834,7 +2804,6 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
{
const GURL url("http://foo2/#a");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1; // Same page_id
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.url = url;
@@ -2862,7 +2831,6 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
{
const GURL url("http://foo3/");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 2; // New page_id
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url;
@@ -2891,7 +2859,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
controller.GoBack();
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, false, url);
+ main_test_rfh()->SendNavigate(entry_id, false, url);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
@@ -2903,7 +2871,6 @@ TEST_F(NavigationControllerTest, PushStateWithoutPreviousEntry)
ASSERT_FALSE(controller_impl().GetLastCommittedEntry());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
GURL url("http://foo");
- params.page_id = 1;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url;
@@ -2962,7 +2929,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(url_index, entry_id, true, url);
+ main_test_rfh()->SendNavigate(entry_id, true, url);
}
EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount);
@@ -2976,7 +2943,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(url_index, entry_id, true, url);
+ main_test_rfh()->SendNavigate(entry_id, true, url);
url_index++;
// We should have got a pruned navigation.
@@ -2996,7 +2963,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(url_index, entry_id, true, url);
+ main_test_rfh()->SendNavigate(entry_id, true, url);
url_index++;
}
EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount);
@@ -3017,7 +2984,6 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
NavigationControllerImpl::CreateNavigationEntry(
url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
browser_context());
- entry->SetPageID(0);
entry->SetTitle(base::ASCIIToUTF16("Title"));
entry->SetPageState(PageState::CreateFromEncodedData("state"));
const base::Time timestamp = base::Time::Now();
@@ -3041,14 +3007,12 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
EXPECT_EQ(1, our_controller.GetEntryCount());
EXPECT_EQ(our_controller.GetEntryAtIndex(0),
our_controller.GetPendingEntry());
- EXPECT_EQ(0, our_controller.GetEntryAtIndex(0)->GetPageID());
// Timestamp should remain the same before the navigation finishes.
EXPECT_EQ(timestamp, our_controller.GetEntryAtIndex(0)->GetTimestamp());
// Say we navigated to that entry.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = our_controller.GetPendingEntry()->GetUniqueID();
params.did_create_new_entry = false;
params.url = url;
@@ -3088,7 +3052,6 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
NavigationControllerImpl::CreateNavigationEntry(
url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
browser_context());
- new_entry->SetPageID(0);
new_entry->SetTitle(base::ASCIIToUTF16("Title"));
new_entry->SetPageState(PageState::CreateFromEncodedData("state"));
entries.push_back(std::move(new_entry));
@@ -3114,7 +3077,6 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
EXPECT_EQ(1, our_controller.GetEntryCount());
EXPECT_EQ(our_controller.GetEntryAtIndex(0),
our_controller.GetPendingEntry());
- EXPECT_EQ(0, our_controller.GetEntryAtIndex(0)->GetPageID());
// This pending navigation may have caused a different navigation to fail,
// which causes the pending entry to be cleared.
@@ -3130,7 +3092,6 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
// Now the pending restored entry commits.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = entry->GetUniqueID();
params.did_create_new_entry = false;
params.url = url;
@@ -3164,7 +3125,7 @@ TEST_F(NavigationControllerTest, Interstitial) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
// Now navigate somewhere with an interstitial.
const GURL url2("http://bar");
@@ -3176,7 +3137,7 @@ TEST_F(NavigationControllerTest, Interstitial) {
// At this point the interstitial will be displayed and the load will still
// be pending. If the user continues, the load will commit.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
// The page should be a normal page again.
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
@@ -3198,27 +3159,27 @@ TEST_F(NavigationControllerTest, RemoveEntry) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
controller.LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
controller.LoadURL(
url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry_id, true, url3);
+ main_test_rfh()->SendNavigate(entry_id, true, url3);
controller.LoadURL(
url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, entry_id, true, url4);
+ main_test_rfh()->SendNavigate(entry_id, true, url4);
controller.LoadURL(
url5, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(4, entry_id, true, url5);
+ main_test_rfh()->SendNavigate(entry_id, true, url5);
// Try to remove the last entry. Will fail because it is the current entry.
EXPECT_FALSE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 1));
@@ -3234,7 +3195,7 @@ TEST_F(NavigationControllerTest, RemoveEntry) {
// Now commit and delete the last entry.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, entry_id, false, url4);
+ main_test_rfh()->SendNavigate(entry_id, false, url4);
EXPECT_TRUE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 1));
EXPECT_EQ(4, controller.GetEntryCount());
EXPECT_EQ(3, controller.GetLastCommittedEntryIndex());
@@ -3266,17 +3227,17 @@ TEST_F(NavigationControllerTest, RemoveEntryWithPending) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
controller.LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
controller.LoadURL(
url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry_id, true, url3);
+ main_test_rfh()->SendNavigate(entry_id, true, url3);
// Go back, but don't commit yet. Check that we can't delete the current
// and pending entries.
@@ -3296,7 +3257,7 @@ TEST_F(NavigationControllerTest, RemoveEntryWithPending) {
// Now commit and ensure we land on the right entry.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, false, url2);
+ main_test_rfh()->SendNavigate(entry_id, false, url2);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
EXPECT_FALSE(controller.GetPendingEntry());
@@ -3320,12 +3281,12 @@ TEST_F(NavigationControllerTest, TransientEntry) {
url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url0);
+ main_test_rfh()->SendNavigate(entry_id, true, url0);
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
notifications.Reset();
@@ -3346,14 +3307,13 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(contents()->GetMaxPageID(), 1);
// Navigate.
controller.LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry_id, true, url2);
+ main_test_rfh()->SendNavigate(entry_id, true, url2);
// We should have navigated, transient entry should be gone.
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
@@ -3366,7 +3326,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, true);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, 0, true, url3);
+ main_test_rfh()->SendNavigate(0, true, url3);
// Transient entry should be gone.
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 4);
@@ -3380,7 +3340,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.SetTransientEntry(std::move(transient_entry));
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(4, entry_id, true, url4);
+ main_test_rfh()->SendNavigate(entry_id, true, url4);
EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 5);
@@ -3400,7 +3360,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.GoToOffset(-1);
entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, entry_id, false, url3);
+ main_test_rfh()->SendNavigate(entry_id, false, url3);
// Add a transient and go to an entry before the current one.
transient_entry.reset(new NavigationEntryImpl);
@@ -3415,7 +3375,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
// Visible entry does not update for history navigations until commit.
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, false, url1);
+ main_test_rfh()->SendNavigate(entry_id, false, url1);
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
// Add a transient and go to an entry after the current one.
@@ -3431,7 +3391,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry_id, false, url2);
+ main_test_rfh()->SendNavigate(entry_id, false, url2);
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
// Add a transient and go forward.
@@ -3447,7 +3407,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_EQ(url3, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, entry_id, false, url3);
+ main_test_rfh()->SendNavigate(entry_id, false, url3);
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
// Add a transient and do an in-page navigation, replacing the current entry.
@@ -3458,7 +3418,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(url3_ref, false);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(3, 0, false, url3_ref);
+ main_test_rfh()->SendNavigate(0, false, url3_ref);
// Transient entry should be gone.
EXPECT_FALSE(controller.GetTransientEntry());
EXPECT_EQ(url3_ref, controller.GetVisibleEntry()->GetURL());
@@ -3484,7 +3444,7 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url0);
+ main_test_rfh()->SendNavigate(entry_id, true, url0);
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
@@ -3508,7 +3468,7 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
// Load of |transient_url| completes.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, transient_url);
+ main_test_rfh()->SendNavigate(entry_id, true, transient_url);
ASSERT_EQ(controller.GetEntryCount(), 2);
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url0);
EXPECT_EQ(controller.GetEntryAtIndex(1)->GetURL(), transient_url);
@@ -3551,7 +3511,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
// Once it commits, the URL and virtual URL should reflect the actual page.
- main_test_rfh()->SendNavigate(0, 0, true, url2);
+ main_test_rfh()->SendNavigate(0, true, url2);
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
@@ -3574,7 +3534,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
navigator->DidStartProvisionalLoad(main_test_rfh(), url2,
base::TimeTicks::Now());
EXPECT_TRUE(controller.GetPendingEntry()->should_replace_entry());
- main_test_rfh()->SendNavigateWithReplacement(0, 0, false, url2);
+ main_test_rfh()->SendNavigateWithReplacement(0, false, url2);
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
}
@@ -3597,7 +3557,7 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
EXPECT_EQ(url0, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url0);
+ main_test_rfh()->SendNavigate(entry_id, true, url0);
// For link clicks (renderer-initiated navigations), the pending entry should
// update before commit but the visible should not.
@@ -3612,7 +3572,7 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
// After commit, both visible should be updated, there should be no pending
// entry, and we should no longer treat the entry as renderer-initiated.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_FALSE(controller.GetLastCommittedEntry()->is_renderer_initiated());
@@ -3783,7 +3743,7 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
// Simulate a commit and then starting a new pending navigation.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, entry_id, true, url1);
+ main_test_rfh()->SendNavigate(entry_id, true, url1);
NavigationController::LoadURLParams load_url2_params(url2);
load_url2_params.transition_type = ui::PAGE_TRANSITION_LINK;
load_url2_params.is_renderer_initiated = true;
@@ -3816,12 +3776,12 @@ TEST_F(NavigationControllerTest, IsInPageNavigation) {
// matches if the URL doesn't look same-origin.
const GURL blank_url(url::kAboutBlankURL);
const url::Origin blank_origin;
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, blank_url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, blank_url);
EXPECT_TRUE(controller.IsURLInPageNavigation(url, url::Origin(url), true,
main_test_rfh()));
// Navigate to URL with no refs.
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(false, url);
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(url, url::Origin(url), false,
@@ -3834,7 +3794,7 @@ 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(1, true, url_with_ref);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_with_ref);
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(
@@ -3891,7 +3851,7 @@ TEST_F(NavigationControllerTest, IsInPageNavigationWithUniversalFileAccess) {
// Allow in page navigation to be cross-origin if existing URL is file scheme.
const GURL file_url("file:///foo/index.html");
const url::Origin file_origin(file_url);
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, file_url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, file_url);
EXPECT_TRUE(file_origin.IsSameOriginWith(
main_test_rfh()->frame_tree_node()->current_origin()));
EXPECT_EQ(0, rph->bad_msg_count());
@@ -3902,7 +3862,6 @@ TEST_F(NavigationControllerTest, IsInPageNavigationWithUniversalFileAccess) {
// Doing a replaceState to a cross-origin URL is thus allowed.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 1;
params.did_create_new_entry = false;
params.url = different_origin_url;
@@ -3929,7 +3888,7 @@ TEST_F(NavigationControllerTest, IsInPageNavigationWithUniversalFileAccess) {
// Don't honor allow_universal_access_from_file_urls if actual URL is
// not file scheme.
const GURL url("http://www.google.com/home.html");
- main_test_rfh()->NavigateAndCommitRendererInitiated(2, true, url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
EXPECT_FALSE(controller.IsURLInPageNavigation(
different_origin_url, url::Origin(different_origin_url), true,
main_test_rfh()));
@@ -3944,7 +3903,7 @@ TEST_F(NavigationControllerTest, SameSubframe) {
NavigationControllerImpl& controller = controller_impl();
// Navigate the main frame.
const GURL url("http://www.google.com/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
// We should be at the first navigation entry.
EXPECT_EQ(controller.GetEntryCount(), 1);
@@ -3960,7 +3919,6 @@ TEST_F(NavigationControllerTest, SameSubframe) {
contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL subframe_url("http://www.google.com/#");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -4136,7 +4094,6 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL url1_sub("http://foo/subframe");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = controller.GetLastCommittedEntry()->GetPageID();
params.nav_entry_id = 0;
params.frame_unique_name = unique_name;
params.did_create_new_entry = false;
@@ -4182,16 +4139,7 @@ TEST_F(NavigationControllerTest, CopyStateFrom) {
ASSERT_EQ(0, other_controller.GetCurrentEntryIndex());
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
- // This is a different site than url1, so the IDs start again at 0.
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(1)->GetPageID());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(0)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
// Ensure the SessionStorageNamespaceMaps are the same size and have
// the same partitons loaded.
@@ -4228,9 +4176,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
SiteInstance* instance1 = controller.GetEntryAtIndex(0)->site_instance();
SiteInstance* instance2 = controller.GetEntryAtIndex(1)->site_instance();
EXPECT_EQ(instance1, instance2);
- EXPECT_EQ(0, controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(1, controller.GetEntryAtIndex(1)->GetPageID());
- EXPECT_EQ(1, contents()->GetMaxPageIDForSiteInstance(instance1));
std::unique_ptr<TestWebContents> other_contents(
static_cast<TestWebContents*>(CreateTestWebContents()));
@@ -4248,9 +4193,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(2)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(1, other_controller.GetEntryAtIndex(1)->GetPageID());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
// A new SiteInstance in a different BrowsingInstance should be used for the
// new tab.
@@ -4258,11 +4200,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
other_controller.GetEntryAtIndex(2)->site_instance();
EXPECT_NE(instance3, instance1);
EXPECT_FALSE(instance3->IsRelatedSiteInstance(instance1));
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- EXPECT_EQ(1, other_contents->GetMaxPageIDForSiteInstance(instance1));
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance3));
}
// Test CopyStateFromAndPrune with 2 urls, the first selected and 1 entry in
@@ -4292,13 +4229,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune2) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(1)->GetPageID());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(1)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
}
// Test CopyStateFromAndPrune with 2 urls, the last selected and 2 entries in
@@ -4329,12 +4259,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune3) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url4, other_controller.GetEntryAtIndex(2)->GetURL());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(2)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
}
// Test CopyStateFromAndPrune with 2 urls, 2 entries in the target, with
@@ -4367,12 +4291,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneNotLast) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(2)->GetURL());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(2)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
}
// Test CopyStateFromAndPrune with 2 urls, the first selected and 1 entry plus
@@ -4410,18 +4328,11 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending) {
// And there should be a pending entry for url4.
ASSERT_TRUE(other_controller.GetPendingEntry());
EXPECT_EQ(url4, other_controller.GetPendingEntry()->GetURL());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(0)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
}
// Test CopyStateFromAndPrune with 1 url in the source, 1 entry and a pending
-// client redirect entry (with the same page ID) in the target. This used to
-// crash because the last committed entry would be pruned but max_page_id
-// remembered the page ID (http://crbug.com/234809).
+// client redirect entry in the target. This used to crash
+// (http://crbug.com/234809).
TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
@@ -4437,8 +4348,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
// Simulate a client redirect, which has the same page ID as entry 2a.
other_controller.LoadURL(
url2b, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
- NavigationEntry* entry = other_controller.GetPendingEntry();
- entry->SetPageID(other_controller.GetLastCommittedEntry()->GetPageID());
other_contents->ExpectSetHistoryOffsetAndLength(1, 2);
other_controller.CopyStateFromAndPrune(&controller, false);
@@ -4458,14 +4367,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
// Let the pending entry commit.
other_contents->TestDidNavigate(other_contents->GetMainFrame(),
- entry->GetPageID(), 0, false, url2b,
- ui::PAGE_TRANSITION_LINK);
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(1)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
+ 0, false, url2b, ui::PAGE_TRANSITION_LINK);
}
// Test CopyStateFromAndPrune with 2 urls, a back navigation pending in the
@@ -4495,13 +4397,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneSourcePending) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(2)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- SiteInstance* instance1 =
- other_controller.GetEntryAtIndex(2)->site_instance();
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance1));
}
// Tests CopyStateFromAndPrune with 3 urls in source, 1 in dest,
@@ -4546,9 +4441,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url4, other_controller.GetEntryAtIndex(2)->GetURL());
- EXPECT_EQ(1, other_controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(2, other_controller.GetEntryAtIndex(1)->GetPageID());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
NavigationControllerImpl::set_max_entry_count_for_testing(original_count);
}
@@ -4568,9 +4460,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneReplaceEntry) {
SiteInstance* instance1 = controller.GetEntryAtIndex(0)->site_instance();
SiteInstance* instance2 = controller.GetEntryAtIndex(1)->site_instance();
EXPECT_EQ(instance1, instance2);
- EXPECT_EQ(0, controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(1, controller.GetEntryAtIndex(1)->GetPageID());
- EXPECT_EQ(1, contents()->GetMaxPageIDForSiteInstance(instance1));
std::unique_ptr<TestWebContents> other_contents(
static_cast<TestWebContents*>(CreateTestWebContents()));
@@ -4587,8 +4476,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneReplaceEntry) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(1)->GetPageID());
// A new SiteInstance in a different BrowsingInstance should be used for the
// new tab.
@@ -4596,11 +4483,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneReplaceEntry) {
other_controller.GetEntryAtIndex(1)->site_instance();
EXPECT_NE(instance3, instance1);
EXPECT_FALSE(instance3->IsRelatedSiteInstance(instance1));
-
- // The max page ID map should be copied over and updated with the max page ID
- // from the current tab.
- EXPECT_EQ(1, other_contents->GetMaxPageIDForSiteInstance(instance1));
- EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance3));
}
// Tests CopyStateFromAndPrune with 3 urls in source, 1 in dest, when the max
@@ -4643,9 +4525,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntriesReplaceEntry) {
EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
EXPECT_EQ(url4, other_controller.GetEntryAtIndex(2)->GetURL());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
- EXPECT_EQ(1, other_controller.GetEntryAtIndex(1)->GetPageID());
- EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
NavigationControllerImpl::set_max_entry_count_for_testing(original_count);
}
@@ -4665,7 +4544,6 @@ TEST_F(NavigationControllerTest, CopyRestoredStateAndNavigate) {
NavigationControllerImpl::CreateNavigationEntry(
kRestoredUrls[i], Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), browser_context());
- entry->SetPageID(static_cast<int>(i));
entries.push_back(std::move(entry));
}
@@ -4836,7 +4714,7 @@ TEST_F(NavigationControllerTest, PruneAllButLastCommittedForPendingNotInList) {
// Try to commit the pending entry.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, entry_id, true, url3);
+ main_test_rfh()->SendNavigate(entry_id, true, url3);
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_EQ(2, controller.GetEntryCount());
@@ -4879,7 +4757,7 @@ TEST_F(NavigationControllerTest, IsInitialNavigation) {
// After commit, it stays false.
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_FALSE(controller.IsInitialNavigation());
@@ -4911,8 +4789,7 @@ TEST_F(NavigationControllerTest, ClearFaviconOnRedirect) {
TestNotificationTracker notifications;
RegisterForAllNavNotifications(&notifications, &controller);
- main_test_rfh()->NavigateAndCommitRendererInitiated(
- 0, true, kPageWithFavicon);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kPageWithFavicon);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4931,7 +4808,6 @@ TEST_F(NavigationControllerTest, ClearFaviconOnRedirect) {
false);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
- 0, // same page ID.
0, // nav_entry_id
false, // no new entry
kPageWithoutFavicon, ui::PAGE_TRANSITION_CLIENT_REDIRECT);
@@ -4956,7 +4832,7 @@ TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {
TestNotificationTracker notifications;
RegisterForAllNavNotifications(&notifications, &controller);
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, kUrl1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4970,13 +4846,13 @@ TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {
favicon_status.valid = true;
// Navigate to another page and go back to the original page.
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, kUrl2);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
- 0, controller.GetEntryAtIndex(0)->GetUniqueID(), false, kUrl1,
+ controller.GetEntryAtIndex(0)->GetUniqueID(), false, kUrl1,
ui::PAGE_TRANSITION_FORWARD_BACK);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -5077,8 +4953,7 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {
// Navigate.
- main_test_rfh()->NavigateAndCommitRendererInitiated(
- 1, true, GURL("http://foo"));
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, GURL("http://foo"));
// Set title and favicon.
base::string16 title(base::ASCIIToUTF16("Title"));
@@ -5092,7 +4967,6 @@ TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {
// history.pushState() is called.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
GURL kUrl2("http://foo#foo");
- params.page_id = 2;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = kUrl2;
@@ -5171,7 +5045,6 @@ TEST_F(NavigationControllerTest, PostThenReplaceStateThenReload) {
// Submit a form.
GURL url("http://foo");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url;
@@ -5187,7 +5060,6 @@ TEST_F(NavigationControllerTest, PostThenReplaceStateThenReload) {
// history.replaceState() is called.
GURL replace_url("http://foo#foo");
- params.page_id = 1;
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.url = replace_url;
@@ -5212,7 +5084,6 @@ TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 0;
params.did_create_new_entry = true;
params.url = url;
@@ -5287,7 +5158,7 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// Start on page A.
const GURL url_a("http://foo.com/a");
- main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url_a);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_a);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(1, controller.GetEntryCount());
@@ -5295,13 +5166,12 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// Go to page B.
const GURL url_b("http://foo.com/b");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url_b);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_b);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
int b_entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
- int b_page_id = controller.GetLastCommittedEntry()->GetPageID();
// Back to page A.
controller.GoBack();
@@ -5316,7 +5186,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(2, true, url_c);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_c);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(2, controller.GetEntryCount());
@@ -5325,7 +5195,7 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
EXPECT_NE(c_entry_id, b_entry_id);
// And then the navigation to B gets committed.
- main_test_rfh()->SendNavigate(b_page_id, b_entry_id, false, url_b);
+ main_test_rfh()->SendNavigate(b_entry_id, false, url_b);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index a1b725ab98b..b450e8ec3ae 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -240,13 +240,12 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::FromNavigationEntry(
}
NavigationEntryImpl::NavigationEntryImpl()
- : NavigationEntryImpl(nullptr, -1, GURL(), Referrer(), base::string16(),
+ : NavigationEntryImpl(nullptr, GURL(), Referrer(), base::string16(),
ui::PAGE_TRANSITION_LINK, false) {
}
NavigationEntryImpl::NavigationEntryImpl(
scoped_refptr<SiteInstanceImpl> instance,
- int page_id,
const GURL& url,
const Referrer& referrer,
const base::string16& title,
@@ -267,7 +266,6 @@ NavigationEntryImpl::NavigationEntryImpl(
page_type_(PAGE_TYPE_NORMAL),
update_virtual_url_with_url_(false),
title_(title),
- page_id_(page_id),
transition_type_(transition_type),
restore_type_(RestoreType::NONE),
is_overriding_user_agent_(false),
@@ -406,14 +404,6 @@ PageState NavigationEntryImpl::GetPageState() const {
return PageState::CreateFromEncodedData(encoded_data);
}
-void NavigationEntryImpl::SetPageID(int page_id) {
- page_id_ = page_id;
-}
-
-int32_t NavigationEntryImpl::GetPageID() const {
- return page_id_;
-}
-
void NavigationEntryImpl::set_site_instance(
scoped_refptr<SiteInstanceImpl> site_instance) {
// TODO(creis): Update all callers and remove this method.
@@ -644,7 +634,6 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace(
copy->update_virtual_url_with_url_ = update_virtual_url_with_url_;
copy->title_ = title_;
copy->favicon_ = favicon_;
- copy->page_id_ = page_id_;
copy->ssl_ = ssl_;
copy->transition_type_ = transition_type_;
copy->user_typed_url_ = user_typed_url_;
@@ -751,11 +740,11 @@ RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
#endif
RequestNavigationParams request_params(
GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(),
- base::Time::Now(), frame_entry.page_state(), GetPageID(), GetUniqueID(),
- is_same_document_history_load, is_history_navigation_in_new_child,
- subframe_unique_names, has_committed_real_load, intended_as_new_entry,
- pending_offset_to_send, current_offset_to_send, current_length_to_send,
- IsViewSourceMode(), should_clear_history_list(), user_gesture);
+ frame_entry.page_state(), GetUniqueID(), is_same_document_history_load,
+ is_history_navigation_in_new_child, subframe_unique_names,
+ has_committed_real_load, intended_as_new_entry, pending_offset_to_send,
+ current_offset_to_send, current_length_to_send, IsViewSourceMode(),
+ should_clear_history_list(), user_gesture);
#if defined(OS_ANDROID)
if (GetDataURLAsString() &&
GetDataURLAsString()->size() <= kMaxLengthOfDataURLString) {
@@ -810,14 +799,6 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry(
const PageState& page_state,
const std::string& method,
int64_t post_id) {
- // We should only have an empty PageState if the navigation is new, and thus
- // page ID is -1.
- if (!page_state.IsValid() && GetPageID() != -1) {
- // Temporarily generate a minidump to diagnose https://crbug.com/568703.
- base::debug::DumpWithoutCrashing();
- NOTREACHED() << "Shouldn't set an empty PageState.";
- }
-
// If this is called for the main frame, the FrameNavigationEntry is
// guaranteed to exist, so just update it directly and return.
if (frame_tree_node->IsMainFrame()) {
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index b9f9408b9f1..4b93695b791 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -85,7 +85,6 @@ class CONTENT_EXPORT NavigationEntryImpl
NavigationEntryImpl();
NavigationEntryImpl(scoped_refptr<SiteInstanceImpl> instance,
- int page_id,
const GURL& url,
const Referrer& referrer,
const base::string16& title,
@@ -114,8 +113,6 @@ class CONTENT_EXPORT NavigationEntryImpl
const base::string16& GetTitle() const override;
void SetPageState(const PageState& state) override;
PageState GetPageState() const override;
- void SetPageID(int page_id) override;
- int32_t GetPageID() const override;
const base::string16& GetTitleForDisplay() const override;
bool IsViewSourceMode() const override;
void SetTransitionType(ui::PageTransition transition_type) override;
@@ -438,7 +435,6 @@ class CONTENT_EXPORT NavigationEntryImpl
bool update_virtual_url_with_url_;
base::string16 title_;
FaviconStatus favicon_;
- int32_t page_id_;
SSLStatus ssl_;
ui::PageTransition transition_type_;
GURL user_typed_url_;
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 8bd79201319..e47fab03b81 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -26,7 +26,7 @@ class NavigationEntryTest : public testing::Test {
instance_ = SiteInstanceImpl::Create(NULL);
entry2_.reset(new NavigationEntryImpl(
- instance_, 3,
+ instance_,
GURL("test:url"),
Referrer(GURL("from"), blink::WebReferrerPolicyDefault),
ASCIIToUTF16("title"),
@@ -137,8 +137,8 @@ TEST_F(NavigationEntryTest, NavigationEntryFavicons) {
// Test SSLStatus inner class
TEST_F(NavigationEntryTest, NavigationEntrySSLStatus) {
// Default (unknown)
- EXPECT_EQ(SECURITY_STYLE_UNKNOWN, entry1_->GetSSL().security_style);
- EXPECT_EQ(SECURITY_STYLE_UNKNOWN, entry2_->GetSSL().security_style);
+ EXPECT_FALSE(entry1_->GetSSL().initialized);
+ EXPECT_FALSE(entry2_->GetSSL().initialized);
EXPECT_FALSE(!!entry1_->GetSSL().certificate);
EXPECT_EQ(0U, entry1_->GetSSL().cert_status);
EXPECT_EQ(-1, entry1_->GetSSL().security_bits);
@@ -180,12 +180,6 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
entry2_->SetPageState(PageState::CreateFromEncodedData("state"));
EXPECT_EQ("state", entry2_->GetPageState().ToEncodedData());
- // Page ID
- EXPECT_EQ(-1, entry1_->GetPageID());
- EXPECT_EQ(3, entry2_->GetPageID());
- entry2_->SetPageID(2);
- EXPECT_EQ(2, entry2_->GetPageID());
-
// Transition type
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
entry1_->GetTransitionType(), ui::PAGE_TRANSITION_LINK));
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 7994b14a80d..ae9e5dbe57a 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -4,20 +4,24 @@
#include "content/browser/frame_host/navigation_handle_impl.h"
-#include <utility>
-
+#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "content/browser/browsing_data/clear_site_data_throttle.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/common/frame_messages.h"
#include "content/common/resource_request_body_impl.h"
+#include "content/common/site_isolation_policy.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_ui_data.h"
+#include "content/public/browser/site_instance.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
@@ -35,6 +39,12 @@ void UpdateThrottleCheckResult(
*to_update = result;
}
+void NotifyAbandonedTransferNavigation(const GlobalRequestID& id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get())
+ rdh->CancelRequest(id.child_id, id.request_id);
+}
+
} // namespace
// static
@@ -42,13 +52,13 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
const GURL& url,
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
- bool is_synchronous,
+ bool is_same_page,
bool is_srcdoc,
const base::TimeTicks& navigation_start,
int pending_nav_entry_id,
bool started_from_context_menu) {
return std::unique_ptr<NavigationHandleImpl>(new NavigationHandleImpl(
- url, frame_tree_node, is_renderer_initiated, is_synchronous, is_srcdoc,
+ url, frame_tree_node, is_renderer_initiated, is_same_page, is_srcdoc,
navigation_start, pending_nav_entry_id, started_from_context_menu));
}
@@ -56,7 +66,7 @@ NavigationHandleImpl::NavigationHandleImpl(
const GURL& url,
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
- bool is_synchronous,
+ bool is_same_page,
bool is_srcdoc,
const base::TimeTicks& navigation_start,
int pending_nav_entry_id,
@@ -68,10 +78,11 @@ NavigationHandleImpl::NavigationHandleImpl(
net_error_code_(net::OK),
render_frame_host_(nullptr),
is_renderer_initiated_(is_renderer_initiated),
- is_same_page_(false),
- is_synchronous_(is_synchronous),
+ is_same_page_(is_same_page),
is_srcdoc_(is_srcdoc),
was_redirected_(false),
+ connection_info_(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
+ original_url_(url),
state_(INITIAL),
is_transferring_(false),
frame_tree_node_(frame_tree_node),
@@ -79,9 +90,19 @@ NavigationHandleImpl::NavigationHandleImpl(
navigation_start_(navigation_start),
pending_nav_entry_id_(pending_nav_entry_id),
request_context_type_(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
- started_from_context_menu_(started_from_context_menu) {
+ should_replace_current_entry_(false),
+ is_download_(false),
+ is_stream_(false),
+ started_from_context_menu_(started_from_context_menu),
+ weak_factory_(this) {
DCHECK(!navigation_start.is_null());
- GetDelegate()->DidStartNavigation(this);
+ redirect_chain_.push_back(url);
+
+ starting_site_instance_ =
+ frame_tree_node_->current_frame_host()->GetSiteInstance();
+
+ if (!IsRendererDebugURL(url_))
+ GetDelegate()->DidStartNavigation(this);
if (IsInMainFrame()) {
TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
@@ -91,7 +112,17 @@ NavigationHandleImpl::NavigationHandleImpl(
}
NavigationHandleImpl::~NavigationHandleImpl() {
- GetDelegate()->DidFinishNavigation(this);
+ // Transfer requests that have not matched up with another navigation request
+ // 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()));
+ }
+
+ if (!IsRendererDebugURL(url_))
+ GetDelegate()->DidFinishNavigation(this);
// Cancel the navigation on the IO thread if the NavigationHandle is being
// destroyed in the middle of the NavigationThrottles checks.
@@ -118,6 +149,10 @@ const GURL& NavigationHandleImpl::GetURL() {
return url_;
}
+SiteInstance* NavigationHandleImpl::GetStartingSiteInstance() {
+ return starting_site_instance_.get();
+}
+
bool NavigationHandleImpl::IsInMainFrame() {
return frame_tree_node_->IsMainFrame();
}
@@ -133,10 +168,6 @@ bool NavigationHandleImpl::IsRendererInitiated() {
return is_renderer_initiated_;
}
-bool NavigationHandleImpl::IsSynchronousNavigation() {
- return is_synchronous_;
-}
-
bool NavigationHandleImpl::IsSrcdoc() {
return is_srcdoc_;
}
@@ -205,9 +236,6 @@ RenderFrameHostImpl* NavigationHandleImpl::GetRenderFrameHost() {
}
bool NavigationHandleImpl::IsSamePage() {
- DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE)
- << "This accessor should not be called before the navigation has "
- "committed.";
return is_same_page_;
}
@@ -215,6 +243,11 @@ const net::HttpResponseHeaders* NavigationHandleImpl::GetResponseHeaders() {
return response_headers_.get();
}
+net::HttpResponseInfo::ConnectionInfo
+NavigationHandleImpl::GetConnectionInfo() {
+ return connection_info_;
+}
+
bool NavigationHandleImpl::HasCommitted() {
return state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE;
}
@@ -237,10 +270,14 @@ void NavigationHandleImpl::Resume() {
} else {
result = CheckWillProcessResponse();
- // If the navigation is about to proceed after processing the response, then
- // it's ready to commit.
- if (result == NavigationThrottle::PROCEED)
- ReadyToCommitNavigation(render_frame_host_);
+ // If the navigation is about to proceed after having been deferred while
+ // processing the response, then it's ready to commit. Determine which
+ // RenderFrameHost should render the response, based on its site (after any
+ // redirects).
+ // Note: if MaybeTransferAndProceed returns false, this means that this
+ // NavigationHandle was deleted, so return immediately.
+ if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed())
+ return;
}
if (result != NavigationThrottle::DEFER)
@@ -300,6 +337,7 @@ NavigationHandleImpl::CallWillRedirectRequestForTesting(
WillRedirectRequest(new_url, new_method_is_post ? "POST" : "GET",
new_referrer_url, new_is_external_protocol,
scoped_refptr<net::HttpResponseHeaders>(),
+ net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
base::Bind(&UpdateThrottleCheckResult, &result));
// Reset the callback to ensure it will not be called later.
@@ -315,7 +353,9 @@ NavigationHandleImpl::CallWillProcessResponseForTesting(
new net::HttpResponseHeaders(raw_response_headers);
NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER;
WillProcessResponse(static_cast<RenderFrameHostImpl*>(render_frame_host),
- headers, SSLStatus(),
+ headers, net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
+ SSLStatus(), GlobalRequestID(), false, false, false,
+ base::Closure(),
base::Bind(&UpdateThrottleCheckResult, &result));
// Reset the callback to ensure it will not be called later.
@@ -326,7 +366,6 @@ NavigationHandleImpl::CallWillProcessResponseForTesting(
void NavigationHandleImpl::CallDidCommitNavigationForTesting(const GURL& url) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 1;
params.nav_entry_id = 1;
params.url = url;
params.referrer = content::Referrer();
@@ -345,10 +384,28 @@ void NavigationHandleImpl::CallDidCommitNavigationForTesting(const GURL& url) {
DidCommitNavigation(params, false, render_frame_host_);
}
+bool NavigationHandleImpl::WasStartedFromContextMenu() const {
+ return started_from_context_menu_;
+}
+
+const GURL& NavigationHandleImpl::GetSearchableFormURL() {
+ return searchable_form_url_;
+}
+
+const std::string& NavigationHandleImpl::GetSearchableFormEncoding() {
+ return searchable_form_encoding_;
+}
+
NavigationData* NavigationHandleImpl::GetNavigationData() {
return navigation_data_.get();
}
+const GlobalRequestID& NavigationHandleImpl::GetGlobalRequestID() {
+ DCHECK(state_ == WILL_PROCESS_RESPONSE || state_ == DEFERRING_RESPONSE ||
+ state_ == READY_TO_COMMIT);
+ return request_id_;
+}
+
void NavigationHandleImpl::InitServiceWorkerHandle(
ServiceWorkerContextWrapper* service_worker_context) {
DCHECK(IsBrowserSideNavigationEnabled());
@@ -402,6 +459,7 @@ void NavigationHandleImpl::WillRedirectRequest(
const GURL& new_referrer_url,
bool new_is_external_protocol,
scoped_refptr<net::HttpResponseHeaders> response_headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info,
const ThrottleChecksFinishedCallback& callback) {
// Update the navigation parameters.
url_ = new_url;
@@ -410,7 +468,9 @@ void NavigationHandleImpl::WillRedirectRequest(
sanitized_referrer_ = Referrer::SanitizeForRequest(url_, sanitized_referrer_);
is_external_protocol_ = new_is_external_protocol;
response_headers_ = response_headers;
+ connection_info_ = connection_info;
was_redirected_ = true;
+ redirect_chain_.push_back(new_url);
if (new_method != "POST")
resource_request_body_ = nullptr;
@@ -428,21 +488,37 @@ void NavigationHandleImpl::WillRedirectRequest(
void NavigationHandleImpl::WillProcessResponse(
RenderFrameHostImpl* render_frame_host,
scoped_refptr<net::HttpResponseHeaders> response_headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info,
const SSLStatus& ssl_status,
+ const GlobalRequestID& request_id,
+ bool should_replace_current_entry,
+ bool is_download,
+ bool is_stream,
+ const base::Closure& transfer_callback,
const ThrottleChecksFinishedCallback& callback) {
DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
render_frame_host_ = render_frame_host;
response_headers_ = response_headers;
+ connection_info_ = connection_info;
+ request_id_ = request_id;
+ should_replace_current_entry_ = should_replace_current_entry;
+ is_download_ = is_download;
+ is_stream_ = is_stream;
state_ = WILL_PROCESS_RESPONSE;
ssl_status_ = ssl_status;
complete_callback_ = callback;
+ transfer_callback_ = transfer_callback;
// Notify each throttle of the response.
NavigationThrottle::ThrottleCheckResult result = CheckWillProcessResponse();
- // If the navigation is about to proceed, then it's ready to commit.
- if (result == NavigationThrottle::PROCEED)
- ReadyToCommitNavigation(render_frame_host);
+ // If the navigation is done processing the response, then it's ready to
+ // commit. Determine which RenderFrameHost should render the response, based
+ // on its site (after any redirects).
+ // Note: if MaybeTransferAndProceed returns false, this means that this
+ // NavigationHandle was deleted, so return immediately.
+ if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed())
+ return;
// If the navigation is not deferred, run the callback.
if (result != NavigationThrottle::DEFER)
@@ -455,9 +531,7 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
render_frame_host_ = render_frame_host;
state_ = READY_TO_COMMIT;
- // Only notify the WebContentsObservers when PlzNavigate is enabled, as
- // |render_frame_host_| may be wrong in the case of transfer navigations.
- if (IsBrowserSideNavigationEnabled())
+ if (!IsRendererDebugURL(url_))
GetDelegate()->ReadyToCommitNavigation(this);
}
@@ -473,7 +547,6 @@ void NavigationHandleImpl::DidCommitNavigation(
has_user_gesture_ = (params.gesture == NavigationGestureUser);
transition_ = params.transition;
render_frame_host_ = render_frame_host;
- is_same_page_ = same_page;
// If an error page reloads, net_error_code might be 200 but we still want to
// count it as an error page.
@@ -485,6 +558,17 @@ void NavigationHandleImpl::DidCommitNavigation(
}
}
+void NavigationHandleImpl::Transfer() {
+ DCHECK(!IsBrowserSideNavigationEnabled());
+ // This is an actual transfer. Inform the NavigationResourceThrottle. This
+ // will allow to mark the URLRequest as transferring. When it is marked as
+ // transferring, the URLRequest can no longer be cancelled by its original
+ // RenderFrame. Instead it will persist until being picked up by the transfer
+ // RenderFrame, even if the original RenderFrame is destroyed.
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, transfer_callback_);
+ transfer_callback_.Reset();
+}
+
NavigationThrottle::ThrottleCheckResult
NavigationHandleImpl::CheckWillStartRequest() {
DCHECK(state_ == WILL_SEND_REQUEST || state_ == DEFERRING_START);
@@ -581,6 +665,96 @@ NavigationHandleImpl::CheckWillProcessResponse() {
return NavigationThrottle::PROCEED;
}
+bool NavigationHandleImpl::MaybeTransferAndProceed() {
+ DCHECK_EQ(WILL_PROCESS_RESPONSE, state_);
+
+ // Check if the navigation should transfer. This may result in the
+ // destruction of this NavigationHandle, and the cancellation of the request.
+ if (!MaybeTransferAndProceedInternal())
+ return false;
+
+ // Inform observers that the navigation is now ready to commit, unless a
+ // transfer of the navigation failed.
+ ReadyToCommitNavigation(render_frame_host_);
+ return true;
+}
+
+bool NavigationHandleImpl::MaybeTransferAndProceedInternal() {
+ DCHECK(render_frame_host_);
+
+ // PlzNavigate: the final RenderFrameHost handling this navigation has been
+ // decided before calling WillProcessResponse in
+ // NavigationRequest::OnResponseStarted.
+ // TODO(clamy): See if PlzNavigate could use this code to check whether to
+ // use the RFH determined at the start of the navigation or to switch to
+ // another one.
+ if (IsBrowserSideNavigationEnabled())
+ return true;
+
+ // A navigation from a RenderFrame that is no longer active should not attempt
+ // to transfer.
+ if (!render_frame_host_->is_active()) {
+ // This will cause the deletion of this NavigationHandle and the
+ // cancellation of the navigation.
+ // TODO(clamy): Remove the logging code once we understand better how we can
+ // get there.
+ base::debug::DumpWithoutCrashing();
+ render_frame_host_->SetNavigationHandle(nullptr);
+ 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.
+ //
+ // Similarly, HTTP 204 (No Content) responses leave the renderer showing the
+ // previous page. The navigation should be allowed to finish without running
+ // the unload handler or swapping in the pending RenderFrameHost.
+ if (is_download_ || is_stream_ ||
+ (response_headers_.get() && response_headers_->response_code() == 204)) {
+ return true;
+ }
+
+ // The content embedder can decide that a transfer to a different process is
+ // required for this URL.
+ bool should_transfer =
+ GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
+ frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
+ original_url_, url_);
+
+ RenderFrameHostManager* manager =
+ render_frame_host_->frame_tree_node()->render_manager();
+
+ // In the site-per-process model, the RenderFrameHostManager may also decide
+ // (independently from the content embedder's ShouldSwapProcessesForRedirect
+ // 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(
+ render_frame_host_->GetProcess()->GetID())) {
+ should_transfer |= manager->IsRendererTransferNeededForNavigation(
+ render_frame_host_, url_);
+ }
+
+ // Start the transfer if needed.
+ if (should_transfer) {
+ // This may destroy the NavigationHandle if the transfer fails.
+ base::WeakPtr<NavigationHandleImpl> weak_self = weak_factory_.GetWeakPtr();
+ manager->OnCrossSiteResponse(render_frame_host_, request_id_,
+ redirect_chain_, sanitized_referrer_,
+ transition_, should_replace_current_entry_);
+ if (!weak_self)
+ return false;
+ }
+
+ return true;
+}
+
void NavigationHandleImpl::RunCompleteCallback(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result != NavigationThrottle::DEFER);
@@ -619,8 +793,4 @@ void NavigationHandleImpl::RegisterNavigationThrottles() {
}
}
-bool NavigationHandleImpl::WasStartedFromContextMenu() const {
- return started_from_context_menu_;
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index 1c0aeaf018c..c02844b80f4 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -8,7 +8,11 @@
#include "content/public/browser/navigation_handle.h"
#include <stddef.h>
+
+#include <memory>
#include <string>
+#include <utility>
+#include <vector>
#include "base/callback.h"
#include "base/macros.h"
@@ -17,6 +21,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/common/content_export.h"
+#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/ssl_status.h"
@@ -76,7 +81,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GURL& url,
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
- bool is_synchronous,
+ bool is_same_page,
bool is_srcdoc,
const base::TimeTicks& navigation_start,
int pending_nav_entry_id,
@@ -85,10 +90,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// NavigationHandle implementation:
const GURL& GetURL() override;
+ SiteInstance* GetStartingSiteInstance() override;
bool IsInMainFrame() override;
bool IsParentMainFrame() override;
bool IsRendererInitiated() override;
- bool IsSynchronousNavigation() override;
bool IsSrcdoc() override;
bool WasServerRedirect() override;
int GetFrameTreeNodeId() override;
@@ -105,6 +110,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool HasCommitted() override;
bool IsErrorPage() override;
const net::HttpResponseHeaders* GetResponseHeaders() override;
+ net::HttpResponseInfo::ConnectionInfo GetConnectionInfo() override;
void Resume() override;
void CancelDeferredNavigation(
NavigationThrottle::ThrottleCheckResult result) override;
@@ -126,6 +132,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const std::string& raw_response_header) override;
void CallDidCommitNavigationForTesting(const GURL& url) override;
bool WasStartedFromContextMenu() const override;
+ const GURL& GetSearchableFormURL() override;
+ const std::string& GetSearchableFormEncoding() override;
+ const GlobalRequestID& GetGlobalRequestID() override;
NavigationData* GetNavigationData() override;
@@ -215,6 +224,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GURL& new_referrer_url,
bool new_is_external_protocol,
scoped_refptr<net::HttpResponseHeaders> response_headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info,
const ThrottleChecksFinishedCallback& callback);
// Called when the URLRequest has delivered response headers and metadata.
@@ -223,11 +233,19 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// NavigationHandle will not call |callback| with a result of DEFER.
// If the result is PROCEED, then 'ReadyToCommitNavigation' will be called
// with |render_frame_host| and |response_headers| just before calling
- // |callback|.
+ // |callback|. Should a transfer navigation happen, |transfer_callback| will
+ // be run on the IO thread.
+ // PlzNavigate: transfer navigations are not possible.
void WillProcessResponse(
RenderFrameHostImpl* render_frame_host,
scoped_refptr<net::HttpResponseHeaders> response_headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info,
const SSLStatus& ssl_status,
+ const GlobalRequestID& request_id,
+ bool should_replace_current_entry,
+ bool is_download,
+ bool is_stream,
+ const base::Closure& transfer_callback,
const ThrottleChecksFinishedCallback& callback);
// Returns the FrameTreeNode this navigation is happening in.
@@ -254,10 +272,18 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
SSLStatus ssl_status() { return ssl_status_; }
+ // Called when the navigation is transferred to a different renderer.
+ void Transfer();
+
NavigationUIData* navigation_ui_data() const {
return navigation_ui_data_.get();
}
+ void set_searchable_form_url(const GURL& url) { searchable_form_url_ = url; }
+ void set_searchable_form_encoding(const std::string& encoding) {
+ searchable_form_encoding_ = encoding;
+ }
+
private:
friend class NavigationHandleImplTest;
@@ -279,7 +305,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
NavigationHandleImpl(const GURL& url,
FrameTreeNode* frame_tree_node,
bool is_renderer_initiated,
- bool is_synchronous,
+ bool is_same_page,
bool is_srcdoc,
const base::TimeTicks& navigation_start,
int pending_nav_entry_id,
@@ -289,6 +315,19 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
NavigationThrottle::ThrottleCheckResult CheckWillRedirectRequest();
NavigationThrottle::ThrottleCheckResult CheckWillProcessResponse();
+ // Called when WillProcessResponse checks are done, to find the final
+ // RenderFrameHost for the navigation. Checks whether the navigation should be
+ // transferred. Returns false if the transfer attempt results in the
+ // destruction of this NavigationHandle and the navigation should no longer
+ // proceed. This can happen when the RenderFrameHostManager determines a
+ // transfer is needed, but WebContentsDelegate::ShouldTransferNavigation
+ // returns false.
+ bool MaybeTransferAndProceed();
+
+ // Helper method for MaybeTransferAndProceed. Returns false if the transfer
+ // attempt results in the destruction of this NavigationHandle.
+ bool MaybeTransferAndProceedInternal();
+
// Helper function to run and reset the |complete_callback_|. This marks the
// end of a round of NavigationThrottleChecks.
void RunCompleteCallback(NavigationThrottle::ThrottleCheckResult result);
@@ -301,6 +340,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// See NavigationHandle for a description of those member variables.
GURL url_;
+ scoped_refptr<SiteInstance> starting_site_instance_;
Referrer sanitized_referrer_;
bool has_user_gesture_;
ui::PageTransition transition_;
@@ -308,11 +348,15 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
net::Error net_error_code_;
RenderFrameHostImpl* render_frame_host_;
const bool is_renderer_initiated_;
- bool is_same_page_;
- const bool is_synchronous_;
+ const bool is_same_page_;
const bool is_srcdoc_;
bool was_redirected_;
scoped_refptr<net::HttpResponseHeaders> response_headers_;
+ net::HttpResponseInfo::ConnectionInfo connection_info_;
+
+ // The original url of the navigation. This may differ from |url_| if the
+ // navigation encounters redirects.
+ const GURL original_url_;
// The HTTP method used for the navigation.
std::string method_;
@@ -364,9 +408,30 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
SSLStatus ssl_status_;
+ // The id of the URLRequest tied to this navigation.
+ GlobalRequestID request_id_;
+
+ // Whether the current NavigationEntry should be replaced upon commit.
+ bool should_replace_current_entry_;
+
+ // The chain of redirects.
+ std::vector<GURL> redirect_chain_;
+
+ // A callback to run on the IO thread if the navigation transfers.
+ base::Closure transfer_callback_;
+
+ // Whether the navigation ended up being a download or a stream.
+ bool is_download_;
+ bool is_stream_;
+
// False by default unless the navigation started within a context menu.
bool started_from_context_menu_;
+ GURL searchable_form_url_;
+ std::string searchable_form_encoding_;
+
+ 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 37bfde78d15..cc67da3a677 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -35,7 +35,7 @@ class NavigationHandleObserver : public WebContentsObserver {
is_main_frame_(false),
is_parent_main_frame_(false),
is_renderer_initiated_(true),
- is_synchronous_(false),
+ is_same_page_(false),
is_srcdoc_(false),
was_redirected_(false),
frame_tree_node_id_(-1),
@@ -55,7 +55,7 @@ class NavigationHandleObserver : public WebContentsObserver {
is_main_frame_ = navigation_handle->IsInMainFrame();
is_parent_main_frame_ = navigation_handle->IsParentMainFrame();
is_renderer_initiated_ = navigation_handle->IsRendererInitiated();
- is_synchronous_ = navigation_handle->IsSynchronousNavigation();
+ is_same_page_ = navigation_handle->IsSamePage();
is_srcdoc_ = navigation_handle->IsSrcdoc();
was_redirected_ = navigation_handle->WasServerRedirect();
frame_tree_node_id_ = navigation_handle->GetFrameTreeNodeId();
@@ -67,7 +67,7 @@ class NavigationHandleObserver : public WebContentsObserver {
DCHECK_EQ(is_main_frame_, navigation_handle->IsInMainFrame());
DCHECK_EQ(is_parent_main_frame_, navigation_handle->IsParentMainFrame());
- DCHECK_EQ(is_synchronous_, navigation_handle->IsSynchronousNavigation());
+ DCHECK_EQ(is_same_page_, navigation_handle->IsSamePage());
DCHECK_EQ(is_renderer_initiated_, navigation_handle->IsRendererInitiated());
DCHECK_EQ(is_srcdoc_, navigation_handle->IsSrcdoc());
DCHECK_EQ(frame_tree_node_id_, navigation_handle->GetFrameTreeNodeId());
@@ -95,7 +95,7 @@ class NavigationHandleObserver : public WebContentsObserver {
bool is_main_frame() { return is_main_frame_; }
bool is_parent_main_frame() { return is_parent_main_frame_; }
bool is_renderer_initiated() { return is_renderer_initiated_; }
- bool is_synchronous() { return is_synchronous_; }
+ bool is_same_page() { return is_same_page_; }
bool is_srcdoc() { return is_srcdoc_; }
bool was_redirected() { return was_redirected_; }
int frame_tree_node_id() { return frame_tree_node_id_; }
@@ -114,7 +114,7 @@ class NavigationHandleObserver : public WebContentsObserver {
bool is_main_frame_;
bool is_parent_main_frame_;
bool is_renderer_initiated_;
- bool is_synchronous_;
+ bool is_same_page_;
bool is_srcdoc_;
bool was_redirected_;
int frame_tree_node_id_;
@@ -318,8 +318,8 @@ class NavigationHandleImplBrowserTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
};
@@ -518,9 +518,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySrcdoc) {
EXPECT_TRUE(observer.is_srcdoc());
}
-// Ensure that the IsSynchronousNavigation() method on NavigationHandle behaves
-// correctly.
-IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySynchronous) {
+// Ensure that the IsSamePage() method on NavigationHandle behaves correctly.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySamePage) {
GURL url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a())"));
EXPECT_TRUE(NavigateToURL(shell(), url));
@@ -528,15 +527,60 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySynchronous) {
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
+ {
+ NavigationHandleObserver observer(
+ shell()->web_contents(),
+ embedded_test_server()->GetURL("a.com", "/foo"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "window.history.pushState({}, '', 'foo');"));
- NavigationHandleObserver observer(
- shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar"));
- EXPECT_TRUE(ExecuteScript(root->child_at(0),
- "window.history.pushState({}, '', 'bar');"));
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.is_same_page());
+ }
+ {
+ NavigationHandleObserver observer(
+ shell()->web_contents(),
+ embedded_test_server()->GetURL("a.com", "/bar"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "window.history.replaceState({}, '', 'bar');"));
- EXPECT_TRUE(observer.has_committed());
- EXPECT_FALSE(observer.is_error());
- EXPECT_TRUE(observer.is_synchronous());
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.is_same_page());
+ }
+ {
+ NavigationHandleObserver observer(
+ shell()->web_contents(),
+ embedded_test_server()->GetURL("a.com", "/bar#frag"));
+ EXPECT_TRUE(
+ ExecuteScript(root->child_at(0), "window.location.replace('#frag');"));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.is_same_page());
+ }
+
+ GURL about_blank_url(url::kAboutBlankURL);
+ {
+ NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
+ EXPECT_TRUE(ExecuteScript(
+ root, "document.body.appendChild(document.createElement('iframe'));"));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_FALSE(observer.is_same_page());
+ EXPECT_EQ(about_blank_url, observer.last_committed_url());
+ }
+ {
+ NavigationHandleObserver observer(shell()->web_contents(), about_blank_url);
+ NavigateFrameToURL(root->child_at(0), about_blank_url);
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_FALSE(observer.is_same_page());
+ EXPECT_EQ(about_blank_url, observer.last_committed_url());
+ }
}
// Ensure that a NavigationThrottle can cancel the navigation at navigation
@@ -695,7 +739,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
// Starts and verifies the main frame navigation.
shell()->LoadURL(main_url);
- EXPECT_TRUE(main_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(main_manager.WaitForRequestStart());
// The throttle should not be null.
EXPECT_NE(previous_throttle, installer.navigation_throttle());
// Checks the only URL recorded so far is the one expected for the main frame.
@@ -709,7 +753,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
// Ditto for frame b navigation.
main_manager.WaitForNavigationFinished();
- EXPECT_TRUE(b_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(b_manager.WaitForRequestStart());
EXPECT_NE(previous_throttle, installer.navigation_throttle());
EXPECT_EQ(b_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
@@ -719,7 +763,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
// Ditto for frame c navigation.
b_manager.WaitForNavigationFinished();
- EXPECT_TRUE(c_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(c_manager.WaitForRequestStart());
EXPECT_NE(previous_throttle, installer.navigation_throttle());
EXPECT_EQ(c_url, url_recorder.urls().back());
EXPECT_EQ(3ul, url_recorder.urls().size());
@@ -757,7 +801,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
shell(), "window.domAutomationController.send(clickSameSiteLink());",
&success));
EXPECT_TRUE(success);
- EXPECT_TRUE(link_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(link_manager.WaitForRequestStart());
EXPECT_EQ(link_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
EXPECT_EQ(REQUEST_CONTEXT_TYPE_HYPERLINK,
@@ -790,7 +834,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
GURL submit_url("javascript:submitForm('isubmit')");
shell()->LoadURL(submit_url);
- EXPECT_TRUE(post_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(post_manager.WaitForRequestStart());
EXPECT_EQ(post_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
EXPECT_EQ(REQUEST_CONTEXT_TYPE_FORM,
@@ -823,7 +867,7 @@ class NavigationHandleImplHttpsUpgradeBrowserTest
// iframe_secure_url never happened and the expected upgrade may not be
// working.
shell()->LoadURL(start_url);
- EXPECT_TRUE(navigation_manager.WaitForWillStartRequest());
+ EXPECT_TRUE(navigation_manager.WaitForRequestStart());
// The main frame should have finished navigating while the iframe should
// have just started.
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
index 315f9ea88c5..ff2f74896b7 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -8,6 +8,7 @@
#include "content/public/browser/ssl_status.h"
#include "content/public/common/request_context_type.h"
#include "content/test/test_render_frame_host.h"
+#include "content/test/test_web_contents.h"
namespace content {
@@ -71,6 +72,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
base::TimeTicks::Now(), 0, false);
EXPECT_EQ(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
test_handle_->request_context_type_);
+ contents()->GetMainFrame()->InitializeRenderFrameIfNeeded();
}
void TearDown() override {
@@ -125,6 +127,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
// the NavigationHandleImplTest.
test_handle_->WillRedirectRequest(
GURL(), "GET", GURL(), false, scoped_refptr<net::HttpResponseHeaders>(),
+ net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
base::Unretained(this)));
}
@@ -138,11 +141,14 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
was_callback_called_ = false;
callback_result_ = NavigationThrottle::DEFER;
- // It's safe to use base::Unretained since the NavigationHandle is owned by
- // the NavigationHandleImplTest.
+ // It's safe to use base::Unretained since the NavigationHandle is owned
+ // by the NavigationHandleImplTest. The ConnectionInfo is different from
+ // that sent to WillRedirectRequest to verify that it's correctly plumbed
+ // in both cases.
test_handle_->WillProcessResponse(
- main_test_rfh(),
- scoped_refptr<net::HttpResponseHeaders>(), SSLStatus(),
+ main_test_rfh(), scoped_refptr<net::HttpResponseHeaders>(),
+ net::HttpResponseInfo::CONNECTION_INFO_QUIC_35, SSLStatus(),
+ GlobalRequestID(), false, false, false, base::Closure(),
base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
base::Unretained(this)));
}
@@ -189,16 +195,33 @@ TEST_F(NavigationHandleImplTest, SimpleDataChecks) {
SimulateWillStartRequest();
EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
test_handle()->GetRequestContextType());
+ EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
+ test_handle()->GetConnectionInfo());
test_handle()->Resume();
SimulateWillRedirectRequest();
EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
test_handle()->GetRequestContextType());
+ EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
+ test_handle()->GetConnectionInfo());
test_handle()->Resume();
SimulateWillProcessResponse();
EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
test_handle()->GetRequestContextType());
+ EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
+ test_handle()->GetConnectionInfo());
+}
+
+TEST_F(NavigationHandleImplTest, SimpleDataCheckNoRedirect) {
+ SimulateWillStartRequest();
+ EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
+ test_handle()->GetConnectionInfo());
+
+ test_handle()->Resume();
+ SimulateWillProcessResponse();
+ EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
+ test_handle()->GetConnectionInfo());
}
// Checks that a deferred navigation can be properly resumed.
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index e5995fba038..4c244854955 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -15,6 +16,7 @@
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/browser/site_instance_impl.h"
@@ -29,6 +31,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_response.h"
+#include "content/public/common/url_constants.h"
#include "net/base/load_flags.h"
#include "net/base/url_util.h"
#include "net/http/http_request_headers.h"
@@ -56,10 +59,11 @@ void UpdateLoadFlagsWithCacheFlags(
*load_flags |= net::LOAD_BYPASS_CACHE;
break;
case FrameMsg_Navigate_Type::RESTORE:
- *load_flags |= net::LOAD_PREFERRING_CACHE;
+ *load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
break;
case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
- *load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ *load_flags |=
+ net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
break;
case FrameMsg_Navigate_Type::NORMAL:
if (is_post)
@@ -123,6 +127,11 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
headers->SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
GetContentClient()->GetUserAgent());
+
+ // Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational
+ // requests, as described in
+ // https://w3c.github.io/webappsec/specs/upgrade/#feature-detect
+ headers->AddHeaderFromString("Upgrade-Insecure-Requests: 1");
}
} // namespace
@@ -183,9 +192,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
false, // is_overriding_user_agent
std::vector<GURL>(), // redirects
false, // can_load_local_resources
- base::Time::Now(), // request_time
PageState(), // page_state
- -1, // page_id
0, // nav_entry_id
false, // is_same_document_history_load
false, // is_history_navigation_in_new_child
@@ -297,13 +304,20 @@ void NavigationRequest::BeginNavigation() {
void NavigationRequest::CreateNavigationHandle(int pending_nav_entry_id) {
// TODO(nasko): Update the NavigationHandle creation to ensure that the
- // proper values are specified for is_synchronous and is_srcdoc.
+ // proper values are specified for is_same_page and is_srcdoc.
navigation_handle_ = NavigationHandleImpl::Create(
common_params_.url, frame_tree_node_, !browser_initiated_,
- false, // is_synchronous
+ false, // is_same_page
false, // is_srcdoc
common_params_.navigation_start, pending_nav_entry_id,
false); // started_in_context_menu
+
+ if (!begin_params_.searchable_form_url.is_empty()) {
+ navigation_handle_->set_searchable_form_url(
+ begin_params_.searchable_form_url);
+ navigation_handle_->set_searchable_form_encoding(
+ begin_params_.searchable_form_encoding);
+ }
}
void NavigationRequest::TransferNavigationHandleOwnership(
@@ -333,15 +347,26 @@ void NavigationRequest::OnRequestRedirected(
common_params_.method = redirect_info.new_method;
common_params_.referrer.url = GURL(redirect_info.new_referrer);
- // TODO(clamy): Have CSP + security upgrade checks here.
+ // For non browser initiated navigations we need to check if the source has
+ // access to the URL. We always allow browser initiated requests.
// TODO(clamy): Kill the renderer if FilterURL fails?
+ GURL url = common_params_.url;
+ if (!browser_initiated_ && source_site_instance()) {
+ source_site_instance()->GetProcess()->FilterURL(false, &url);
+ // FilterURL sets the URL to about:blank if the CSP checks prevent the
+ // renderer from accessing it.
+ if ((url == url::kAboutBlankURL) && (url != common_params_.url)) {
+ frame_tree_node_->ResetNavigationRequest(false);
+ return;
+ }
+ }
// It's safe to use base::Unretained because this NavigationRequest owns the
// NavigationHandle where the callback will be stored.
// TODO(clamy): pass the real value for |is_external_protocol| if needed.
navigation_handle_->WillRedirectRequest(
common_params_.url, common_params_.method, common_params_.referrer.url,
- false, response->head.headers,
+ false, response->head.headers, response->head.connection_info,
base::Bind(&NavigationRequest::OnRedirectChecksComplete,
base::Unretained(this)));
}
@@ -367,14 +392,16 @@ void NavigationRequest::OnResponseStarted(
}
// Update the service worker params of the request params.
- request_params_.should_create_service_worker =
- (frame_tree_node_->pending_sandbox_flags() &
- blink::WebSandboxFlags::Origin) != blink::WebSandboxFlags::Origin;
- if (navigation_handle_->service_worker_handle()) {
- request_params_.service_worker_provider_id =
- navigation_handle_->service_worker_handle()
- ->service_worker_provider_host_id();
- }
+ bool did_create_service_worker_host =
+ navigation_handle_->service_worker_handle() &&
+ navigation_handle_->service_worker_handle()
+ ->service_worker_provider_host_id() !=
+ kInvalidServiceWorkerProviderId;
+ request_params_.service_worker_provider_id =
+ did_create_service_worker_host
+ ? navigation_handle_->service_worker_handle()
+ ->service_worker_provider_host_id()
+ : kInvalidServiceWorkerProviderId;
// Update the lofi state of the request.
if (response->head.is_using_lofi)
@@ -406,8 +433,13 @@ void NavigationRequest::OnResponseStarted(
body_ = std::move(body);
// Check if the navigation should be allowed to proceed.
+ // TODO(clamy): pass the right values for request_id, is_download and
+ // is_stream.
navigation_handle_->WillProcessResponse(
- render_frame_host, response->head.headers.get(), ssl_status,
+ render_frame_host, response->head.headers.get(),
+ response->head.connection_info, ssl_status, GlobalRequestID(),
+ common_params_.should_replace_current_entry, false, false,
+ base::Closure(),
base::Bind(&NavigationRequest::OnWillProcessResponseChecksComplete,
base::Unretained(this)));
}
@@ -444,6 +476,11 @@ void NavigationRequest::OnStartChecksComplete(
return;
}
+ if (result == NavigationThrottle::BLOCK_REQUEST) {
+ OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT);
+ return;
+ }
+
// Use the SiteInstance of the navigating RenderFrameHost to get access to
// the StoragePartition. Using the url of the navigation will result in a
// wrong StoragePartition being picked when a WebView is navigating.
@@ -465,6 +502,7 @@ void NavigationRequest::OnStartChecksComplete(
bool can_create_service_worker =
(frame_tree_node_->pending_sandbox_flags() &
blink::WebSandboxFlags::Origin) != blink::WebSandboxFlags::Origin;
+ request_params_.should_create_service_worker = can_create_service_worker;
if (can_create_service_worker) {
ServiceWorkerContextWrapper* service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
@@ -491,13 +529,21 @@ void NavigationRequest::OnStartChecksComplete(
if (navigation_handle_->navigation_ui_data())
navigation_ui_data = navigation_handle_->navigation_ui_data()->Clone();
+ bool is_for_guests_only =
+ navigation_handle_->GetStartingSiteInstance()->GetSiteURL().
+ SchemeIs(kGuestScheme);
+
+ bool report_raw_headers =
+ RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(frame_tree_node_);
+
loader_ = NavigationURLLoader::Create(
frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
base::MakeUnique<NavigationRequestInfo>(
common_params_, begin_params_, first_party_for_cookies,
frame_tree_node_->current_origin(), frame_tree_node_->IsMainFrame(),
parent_is_main_frame, IsSecureFrame(frame_tree_node_->parent()),
- frame_tree_node_->frame_tree_node_id()),
+ frame_tree_node_->frame_tree_node_id(), is_for_guests_only,
+ report_raw_headers),
std::move(navigation_ui_data),
navigation_handle_->service_worker_handle(), this);
}
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index 31a98625704..7d3e82f4c3e 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -24,11 +24,9 @@ class NavigationControllerImpl;
class NavigationHandleImpl;
class NavigationURLLoader;
class NavigationData;
-class NavigatorDelegate;
class ResourceRequestBody;
class SiteInstanceImpl;
class StreamHandle;
-struct NavigationRequestInfo;
// PlzNavigate
// A UI thread object that owns a navigation request until it commits. It
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
index eff32fc37eb..2fa9d972714 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.cc
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -15,7 +15,9 @@ NavigationRequestInfo::NavigationRequestInfo(
bool is_main_frame,
bool parent_is_main_frame,
bool are_ancestors_secure,
- int frame_tree_node_id)
+ int frame_tree_node_id,
+ bool is_for_guests_only,
+ bool report_raw_headers)
: common_params(common_params),
begin_params(begin_params),
first_party_for_cookies(first_party_for_cookies),
@@ -23,7 +25,9 @@ NavigationRequestInfo::NavigationRequestInfo(
is_main_frame(is_main_frame),
parent_is_main_frame(parent_is_main_frame),
are_ancestors_secure(are_ancestors_secure),
- frame_tree_node_id(frame_tree_node_id) {}
+ frame_tree_node_id(frame_tree_node_id),
+ is_for_guests_only(is_for_guests_only),
+ report_raw_headers(report_raw_headers) {}
NavigationRequestInfo::~NavigationRequestInfo() {}
diff --git a/chromium/content/browser/frame_host/navigation_request_info.h b/chromium/content/browser/frame_host/navigation_request_info.h
index 6324a4d773f..53579085c48 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.h
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -16,7 +16,6 @@
#include "url/origin.h"
namespace content {
-class ResourceRequestBody;
// A struct to hold the parameters needed to start a navigation request in
// ResourceDispatcherHost. It is initialized on the UI thread, and then passed
@@ -29,7 +28,9 @@ struct CONTENT_EXPORT NavigationRequestInfo {
bool is_main_frame,
bool parent_is_main_frame,
bool are_ancestors_secure,
- int frame_tree_node_id);
+ int frame_tree_node_id,
+ bool is_for_guests_only,
+ bool report_raw_headers);
~NavigationRequestInfo();
const CommonNavigationParams common_params;
@@ -50,6 +51,10 @@ struct CONTENT_EXPORT NavigationRequestInfo {
const bool are_ancestors_secure;
const int frame_tree_node_id;
+
+ const bool is_for_guests_only;
+
+ const bool report_raw_headers;
};
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 4985d9ec21c..aee61f64d0e 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -38,9 +38,4 @@ void Navigator::OnBeginNavigation(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params) {}
-NavigationHandleImpl* Navigator::GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host) {
- return nullptr;
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index 8ff2d8bc0f8..9f29e553ea7 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -7,13 +7,13 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
#include "ui/base/window_open_disposition.h"
class GURL;
-struct FrameHostMsg_BeginNavigation_Params;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
@@ -25,16 +25,11 @@ namespace content {
class FrameNavigationEntry;
class FrameTreeNode;
-class NavigationControllerImpl;
-class NavigationEntryImpl;
-class NavigationHandleImpl;
class NavigationRequest;
class RenderFrameHostImpl;
class ResourceRequestBodyImpl;
-class StreamHandle;
struct BeginNavigationParams;
struct CommonNavigationParams;
-struct ResourceResponse;
// Implementations of this interface are responsible for performing navigations
// in a node of the FrameTree. Its lifetime is bound to all FrameTreeNode
@@ -72,19 +67,24 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const base::string16& error_description,
bool was_ignored_by_handler) {}
- // The RenderFrameHostImpl has committed a navigation.
+ // The RenderFrameHostImpl has committed a navigation. The Navigator is
+ // responsible for resetting |navigation_handle| at the end of this method and
+ // should not attempt to keep it alive.
+ // Note: it is possible that |navigation_handle| is not the NavigationHandle
+ // stored in the RenderFrameHost that just committed. This happens for example
+ // when a same-page navigation commits while another navigation is ongoing.
+ // The Navigator should use the NavigationHandle provided by this method and
+ // not attempt to access the RenderFrameHost's NavigationsHandle.
virtual void DidNavigate(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {}
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ std::unique_ptr<NavigationHandleImpl> navigation_handle) {}
// Called by the NavigationController to cause the Navigator to navigate
// to the current pending entry. The NavigationController should be called
// back with RendererDidNavigate on success or DiscardPendingEntry on failure.
// The callbacks can be inside of this function, or at some future time.
//
- // The entry has a PageID of -1 if newly created (corresponding to navigation
- // to a new URL).
- //
// If this method returns false, then the navigation is discarded (equivalent
// to calling DiscardPendingEntry on the NavigationController).
//
@@ -117,7 +117,7 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const GURL& url,
bool uses_post,
const scoped_refptr<ResourceRequestBodyImpl>& body,
- SiteInstance* source_site_instance,
+ const std::string& extra_headers,
const Referrer& referrer,
WindowOpenDisposition disposition,
bool should_replace_current_entry,
@@ -137,7 +137,8 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
const std::string& method,
- scoped_refptr<ResourceRequestBodyImpl> post_body) {}
+ scoped_refptr<ResourceRequestBodyImpl> post_body,
+ const std::string& extra_headers) {}
// PlzNavigate
// Called after receiving a BeforeUnloadACK IPC from the renderer. If
@@ -183,14 +184,6 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time) {}
- // Returns the NavigationHandle associated with a navigation in
- // |render_frame_host|. Normally, each frame can have its own
- // NavigationHandle. However, in the case of a navigation to an interstitial
- // page, there's just one NavigationHandle for the whole page (since it's
- // assumed to only have one RenderFrameHost and navigate once).
- virtual NavigationHandleImpl* GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host);
-
// Called when a navigation has failed or the response is 204/205 to discard
// the pending entry in order to avoid url spoofs.
virtual void DiscardPendingEntryIfNeeded(NavigationHandleImpl* handle) {}
diff --git a/chromium/content/browser/frame_host/navigator_delegate.h b/chromium/content/browser/frame_host/navigator_delegate.h
index 0f435bf6433..0eb337c879b 100644
--- a/chromium/content/browser/frame_host/navigator_delegate.h
+++ b/chromium/content/browser/frame_host/navigator_delegate.h
@@ -17,7 +17,6 @@
class GURL;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
-struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
namespace content {
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index d3ae8ea821f..71063d8c46b 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -150,6 +151,15 @@ void NavigatorImpl::DidStartProvisionalLoad(
RenderProcessHost* render_process_host = render_frame_host->GetProcess();
render_process_host->FilterURL(false, &validated_url);
+ // Do not allow browser plugin guests to navigate to non-web URLs, since they
+ // cannot swap processes or grant bindings.
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ if (render_process_host->IsForGuestsOnly() &&
+ !policy->IsWebSafeScheme(validated_url.scheme())) {
+ validated_url = GURL(url::kAboutBlankURL);
+ }
+
if (is_main_frame && !is_error_page) {
DidStartMainFrameNavigation(validated_url,
render_frame_host->GetSiteInstance(),
@@ -197,7 +207,7 @@ void NavigatorImpl::DidStartProvisionalLoad(
render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
validated_url, render_frame_host->frame_tree_node(),
is_renderer_initiated,
- false, // is_synchronous
+ false, // is_same_page
is_iframe_srcdoc, // is_srcdoc
navigation_start, pending_nav_entry_id, started_from_context_menu));
}
@@ -389,6 +399,14 @@ bool NavigatorImpl::NavigateToEntry(
if (is_transfer)
dest_render_frame_host->set_is_loading(true);
+ // A session history navigation should have been accompanied by state.
+ // TODO(creis): This is known to be failing in UseSubframeNavigationEntries
+ // in https://crbug.com/568703, when the PageState on a FrameNavigationEntry
+ // is unexpectedly empty. Until the cause is found, keep this as a DCHECK
+ // and load the URL without PageState.
+ if (is_pending_entry && controller_->GetPendingEntryIndex() != -1)
+ DCHECK(frame_entry.page_state().IsValid());
+
// Navigate in the desired RenderFrameHost.
// We can skip this step in the rare case that this is a transfer navigation
// which began in the chosen RenderFrameHost, since the request has already
@@ -418,9 +436,7 @@ bool NavigatorImpl::NavigateToEntry(
controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount()));
} else {
- // No need to navigate again. Just resume the deferred request.
- dest_render_frame_host->GetProcess()->ResumeDeferredNavigation(
- entry.transferred_global_request_id());
+ dest_render_frame_host->navigation_handle()->set_is_transferring(false);
}
}
@@ -497,7 +513,8 @@ bool NavigatorImpl::NavigateNewChildFrame(
void NavigatorImpl::DidNavigate(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ std::unique_ptr<NavigationHandleImpl> navigation_handle) {
FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree();
bool oopifs_possible = SiteIsolationPolicy::AreCrossProcessFramesPossible();
@@ -604,7 +621,8 @@ void NavigatorImpl::DidNavigate(
int old_entry_count = controller_->GetEntryCount();
LoadCommittedDetails details;
bool did_navigate = controller_->RendererDidNavigate(
- render_frame_host, params, &details, is_navigation_within_page);
+ render_frame_host, params, &details, is_navigation_within_page,
+ navigation_handle.get());
// If the history length and/or offset changed, update other renderers in the
// FrameTree.
@@ -653,9 +671,9 @@ void NavigatorImpl::DidNavigate(
delegate_->DidCommitProvisionalLoad(render_frame_host,
params.url,
transition_type);
- render_frame_host->navigation_handle()->DidCommitNavigation(
- params, is_navigation_within_page, render_frame_host);
- render_frame_host->SetNavigationHandle(nullptr);
+ navigation_handle->DidCommitNavigation(params, is_navigation_within_page,
+ render_frame_host);
+ navigation_handle.reset();
}
if (!did_navigate)
@@ -685,7 +703,7 @@ void NavigatorImpl::DidNavigate(
bool NavigatorImpl::ShouldAssignSiteForURL(const GURL& url) {
// about:blank should not "use up" a new SiteInstance. The SiteInstance can
// still be used for a normal web site.
- if (url == GURL(url::kAboutBlankURL))
+ if (url == url::kAboutBlankURL)
return false;
// The embedder will then have the opportunity to determine if the URL
@@ -698,7 +716,7 @@ void NavigatorImpl::RequestOpenURL(
const GURL& url,
bool uses_post,
const scoped_refptr<ResourceRequestBodyImpl>& body,
- SiteInstance* source_site_instance,
+ const std::string& extra_headers,
const Referrer& referrer,
WindowOpenDisposition disposition,
bool should_replace_current_entry,
@@ -746,33 +764,32 @@ void NavigatorImpl::RequestOpenURL(
true /* is_renderer_initiated */);
params.uses_post = uses_post;
params.post_data = body;
- params.source_site_instance = source_site_instance;
+ params.extra_headers = extra_headers;
if (redirect_chain.size() > 0)
params.redirect_chain = redirect_chain;
params.should_replace_current_entry = should_replace_current_entry;
params.user_gesture = user_gesture;
+ // RequestOpenURL is used only for local frames, so we can get here only if
+ // the navigation is initiated by a frame in the same SiteInstance as this
+ // frame. Note that navigations on RenderFrameProxies do not use
+ // RequestOpenURL and go through RequestTransferURL instead.
+ params.source_site_instance = current_site_instance;
+
if (render_frame_host->web_ui()) {
- // Web UI pages sometimes want to override the page transition type for
- // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
- // automatically generated suggestions). We don't override other types
- // like TYPED because they have different implications (e.g., autocomplete).
- if (ui::PageTransitionCoreTypeIs(
- params.transition, ui::PAGE_TRANSITION_LINK))
- params.transition = render_frame_host->web_ui()->GetLinkTransitionType();
-
- // Note also that we hide the referrer for Web UI pages. We don't really
- // want web sites to see a referrer of "chrome://blah" (and some
- // chrome: URLs might have search terms or other stuff we don't want to
- // send to the site), so we send no referrer.
+ // Note that we hide the referrer for Web UI pages. We don't really want
+ // web sites to see a referrer of "chrome://blah" (and some chrome: URLs
+ // might have search terms or other stuff we don't want to send to the
+ // site), so we send no referrer.
params.referrer = Referrer();
// Navigations in Web UI pages count as browser-initiated navigations.
params.is_renderer_initiated = false;
}
- GetContentClient()->browser()->OverrideOpenURLParams(current_site_instance,
- &params);
+ GetContentClient()->browser()->OverrideNavigationParams(
+ current_site_instance, &params.transition, &params.is_renderer_initiated,
+ &params.referrer);
if (delegate_)
delegate_->RequestOpenURL(render_frame_host, params);
@@ -788,7 +805,8 @@ void NavigatorImpl::RequestTransferURL(
const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
const std::string& method,
- scoped_refptr<ResourceRequestBodyImpl> post_body) {
+ scoped_refptr<ResourceRequestBodyImpl> post_body,
+ const std::string& extra_headers) {
// |method != "POST"| should imply absence of |post_body|.
if (method != "POST" && post_body) {
NOTREACHED();
@@ -825,23 +843,20 @@ void NavigatorImpl::RequestTransferURL(
// navigation. See https://crbug.com/495161.
bool is_renderer_initiated = true;
if (render_frame_host->web_ui()) {
- // Web UI pages sometimes want to override the page transition type for
- // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
- // automatically generated suggestions). We don't override other types
- // like TYPED because they have different implications (e.g., autocomplete).
- if (ui::PageTransitionCoreTypeIs(page_transition, ui::PAGE_TRANSITION_LINK))
- page_transition = render_frame_host->web_ui()->GetLinkTransitionType();
-
- // Note also that we hide the referrer for Web UI pages. We don't really
- // want web sites to see a referrer of "chrome://blah" (and some
- // chrome: URLs might have search terms or other stuff we don't want to
- // send to the site), so we send no referrer.
+ // Note that we hide the referrer for Web UI pages. We don't really want
+ // web sites to see a referrer of "chrome://blah" (and some chrome: URLs
+ // might have search terms or other stuff we don't want to send to the
+ // site), so we send no referrer.
referrer_to_use = Referrer();
// Navigations in Web UI pages count as browser-initiated navigations.
is_renderer_initiated = false;
}
+ GetContentClient()->browser()->OverrideNavigationParams(
+ current_site_instance, &page_transition, &is_renderer_initiated,
+ &referrer_to_use);
+
// Create a NavigationEntry for the transfer, without making it the pending
// entry. Subframe transfers should only be possible in OOPIF-enabled modes,
// and should have a clone of the last committed entry with a
@@ -856,7 +871,7 @@ void NavigatorImpl::RequestTransferURL(
CHECK(SiteIsolationPolicy::UseSubframeNavigationEntries());
if (controller_->GetLastCommittedEntry()) {
entry = controller_->GetLastCommittedEntry()->Clone();
- entry->SetPageID(-1);
+ entry->set_extra_headers(extra_headers);
} else {
// If there's no last committed entry, create an entry for about:blank
// with a subframe entry for our destination.
@@ -864,7 +879,7 @@ void NavigatorImpl::RequestTransferURL(
entry = NavigationEntryImpl::FromNavigationEntry(
controller_->CreateNavigationEntry(
GURL(url::kAboutBlankURL), referrer_to_use, page_transition,
- is_renderer_initiated, std::string(),
+ is_renderer_initiated, extra_headers,
controller_->GetBrowserContext()));
}
entry->AddOrUpdateFrameEntry(
@@ -877,7 +892,7 @@ void NavigatorImpl::RequestTransferURL(
entry = NavigationEntryImpl::FromNavigationEntry(
controller_->CreateNavigationEntry(
dest_url, referrer_to_use, page_transition, is_renderer_initiated,
- std::string(), controller_->GetBrowserContext()));
+ extra_headers, controller_->GetBrowserContext()));
entry->root_node()->frame_entry->set_source_site_instance(
static_cast<SiteInstanceImpl*>(source_site_instance));
entry->SetRedirectChain(redirect_chain);
@@ -1059,11 +1074,6 @@ void NavigatorImpl::LogBeforeUnloadTime(
}
}
-NavigationHandleImpl* NavigatorImpl::GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host) {
- return render_frame_host->navigation_handle();
-}
-
void NavigatorImpl::DiscardPendingEntryIfNeeded(NavigationHandleImpl* handle) {
// Racy conditions can cause a fail message to arrive after its corresponding
// pending entry has been replaced by another navigation. If
@@ -1121,6 +1131,7 @@ void NavigatorImpl::RequestNavigation(FrameTreeNode* frame_tree_node,
// This value must be set here because creating a NavigationRequest might
// change the renderer live/non-live status and change this result.
bool should_dispatch_beforeunload =
+ !is_same_document_history_load &&
frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
FrameMsg_Navigate_Type::Value navigation_type =
GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index b00b1184aca..f9d8fdc28fc 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -56,7 +56,8 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
bool was_ignored_by_handler) override;
void DidNavigate(
RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) override;
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ std::unique_ptr<NavigationHandleImpl> navigation_handle) override;
bool NavigateToPendingEntry(FrameTreeNode* frame_tree_node,
const FrameNavigationEntry& frame_entry,
ReloadType reload_type,
@@ -67,22 +68,22 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const GURL& url,
bool uses_post,
const scoped_refptr<ResourceRequestBodyImpl>& body,
- SiteInstance* source_site_instance,
+ const std::string& extra_headers,
const Referrer& referrer,
WindowOpenDisposition disposition,
bool should_replace_current_entry,
bool user_gesture) override;
- void RequestTransferURL(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- SiteInstance* source_site_instance,
- const std::vector<GURL>& redirect_chain,
- const Referrer& referrer,
- ui::PageTransition page_transition,
- const GlobalRequestID& transferred_global_request_id,
- bool should_replace_current_entry,
- const std::string& method,
- scoped_refptr<ResourceRequestBodyImpl> post_body) override;
+ void RequestTransferURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ SiteInstance* source_site_instance,
+ const std::vector<GURL>& redirect_chain,
+ const Referrer& referrer,
+ ui::PageTransition page_transition,
+ const GlobalRequestID& transferred_global_request_id,
+ bool should_replace_current_entry,
+ const std::string& method,
+ scoped_refptr<ResourceRequestBodyImpl> post_body,
+ const std::string& extra_headers) override;
void OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, bool proceed) override;
void OnBeginNavigation(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
@@ -96,8 +97,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time) override;
void CancelNavigation(FrameTreeNode* frame_tree_node) override;
- NavigationHandleImpl* GetNavigationHandleForFrameHost(
- RenderFrameHostImpl* render_frame_host) override;
void DiscardPendingEntryIfNeeded(NavigationHandleImpl* handle) override;
private:
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 473277c5d4f..5cbcfc1bc21 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -145,7 +145,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
- main_test_rfh()->SendNavigate(0, entry_id, true, kUrl);
+ main_test_rfh()->SendNavigate(entry_id, true, kUrl);
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
@@ -198,7 +198,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
- main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
+ main_test_rfh()->SendNavigate(0, true, kUrl2);
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
@@ -252,7 +252,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
- main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
+ main_test_rfh()->SendNavigate(0, true, kUrl2);
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -459,7 +459,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
- speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl2);
RenderFrameHostImpl* final_rfh = main_test_rfh();
EXPECT_EQ(speculative_rfh, final_rfh);
@@ -504,7 +504,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh));
// Commit the navigation.
- final_speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
+ final_speculative_rfh->SendNavigate(entry_id, true, kUrl2);
RenderFrameHostImpl* final_rfh = main_test_rfh();
ASSERT_TRUE(final_rfh);
EXPECT_NE(rfh, final_rfh);
@@ -573,7 +573,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
// Commit the navigation.
- speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl2);
// Confirm that the commit corresponds to the new request.
ASSERT_TRUE(main_test_rfh());
@@ -644,7 +644,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Commit the navigation.
- main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
+ main_test_rfh()->SendNavigate(0, true, kUrl2);
// Confirm that the commit corresponds to the new request.
ASSERT_TRUE(main_test_rfh());
@@ -705,7 +705,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Commit the navigation.
- main_test_rfh()->SendNavigate(1, 0, true, kUrl1);
+ main_test_rfh()->SendNavigate(0, true, kUrl1);
EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
}
@@ -753,7 +753,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
// Commit the navigation.
- speculative_rfh->SendNavigate(0, entry_id, true, kUrl1);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl1);
EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
}
@@ -814,7 +814,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Commit the navigation.
- main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
+ main_test_rfh()->SendNavigate(0, true, kUrl2);
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
// The SiteInstance did not change.
@@ -846,7 +846,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, Reload) {
main_test_rfh()->PrepareForCommit();
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
- main_test_rfh()->SendNavigate(0, entry_id, false, kUrl);
+ main_test_rfh()->SendNavigate(entry_id, false, kUrl);
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
// Now do a shift+reload.
@@ -896,7 +896,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(node->render_manager()->pending_frame_host());
// Invoke OnDidCommitProvisionalLoad.
- speculative_rfh->SendNavigate(0, entry_id, true, kUrl);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl);
EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
EXPECT_FALSE(node->render_manager()->pending_frame_host());
@@ -967,7 +967,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_NE(site_instance_id, redirect_site_instance_id);
// Invoke OnDidCommitProvisionalLoad.
- speculative_rfh->SendNavigate(0, entry_id, true, kUrlRedirect);
+ speculative_rfh->SendNavigate(entry_id, true, kUrlRedirect);
// Check that the speculative RenderFrameHost was swapped in.
EXPECT_EQ(redirect_site_instance_id,
@@ -995,7 +995,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
EXPECT_TRUE(speculative_rfh->is_loading());
EXPECT_FALSE(node->navigation_request());
EXPECT_NE(main_test_rfh(), speculative_rfh);
- speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl2);
EXPECT_EQ(main_test_rfh(), speculative_rfh);
// Go back to the initial site.
@@ -1168,7 +1168,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteClaimWithinPage) {
// Claim that the navigation was within same page.
int bad_msg_count = process()->bad_msg_count();
GetSpeculativeRenderFrameHost(node)->SendNavigateWithModificationCallback(
- 0, entry_id, true, kUrl2, base::Bind(SetWithinPage, kUrl1));
+ entry_id, true, kUrl2, base::Bind(SetWithinPage, kUrl1));
EXPECT_EQ(process()->bad_msg_count(), bad_msg_count + 1);
}
@@ -1199,7 +1199,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// The first navigation commits. This should clear up the speculative RFH and
// the ongoing NavigationRequest.
- main_test_rfh()->SendNavigate(1, entry_id, true, kUrl2);
+ main_test_rfh()->SendNavigate(entry_id, true, kUrl2);
EXPECT_FALSE(node->navigation_request());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
@@ -1236,7 +1236,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// The first navigation commits. This should clear up the speculative RFH and
// the ongoing NavigationRequest.
- speculative_rfh->SendNavigate(1, entry_id, true, kUrl2);
+ speculative_rfh->SendNavigate(entry_id, true, kUrl2);
EXPECT_FALSE(node->navigation_request());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
EXPECT_EQ(speculative_rfh, main_test_rfh());
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 534fc74ec64..4dcd5811c4e 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -24,7 +24,7 @@ const GURL& RenderFrameHostDelegate::GetMainFrameLastCommittedURL() const {
return GURL::EmptyGURL();
}
-bool RenderFrameHostDelegate::AddMessageToConsole(
+bool RenderFrameHostDelegate::DidAddMessageToConsole(
int32_t level,
const base::string16& message,
int32_t line_no,
@@ -72,7 +72,8 @@ RenderFrameHostDelegate::GetGeolocationServiceContext() {
return nullptr;
}
-WakeLockServiceContext* RenderFrameHostDelegate::GetWakeLockServiceContext() {
+device::WakeLockServiceContext*
+RenderFrameHostDelegate::GetWakeLockServiceContext() {
return nullptr;
}
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index d354978f79c..94cc5615620 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -33,6 +33,11 @@ class Message;
namespace device {
class GeolocationServiceContext;
+class WakeLockServiceContext;
+}
+
+namespace gfx {
+class Rect;
}
namespace content {
@@ -40,13 +45,12 @@ class FrameTreeNode;
class InterstitialPage;
class PageState;
class RenderFrameHost;
-class WakeLockServiceContext;
+class RenderFrameHostImpl;
class WebContents;
struct AXEventNotificationDetails;
struct AXLocationChangeNotificationDetails;
struct ContextMenuParams;
struct FileChooserParams;
-struct TransitionLayerData;
// An interface implemented by an object interested in knowing about the state
// of the RenderFrameHost.
@@ -67,10 +71,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual const GURL& GetMainFrameLastCommittedURL() const;
// A message was added to to the console.
- virtual bool AddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id);
+ virtual bool DidAddMessageToConsole(int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id);
// Informs the delegate whenever a RenderFrameHost is created.
virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) {}
@@ -118,7 +122,6 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// The page's title was changed and should be updated. Only called for the
// top-level frame.
virtual void UpdateTitle(RenderFrameHost* render_frame_host,
- int32_t page_id,
const base::string16& title,
base::i18n::TextDirection title_direction) {}
@@ -168,7 +171,7 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual device::GeolocationServiceContext* GetGeolocationServiceContext();
// Gets the WakeLockServiceContext associated with this delegate.
- virtual WakeLockServiceContext* GetWakeLockServiceContext();
+ virtual device::WakeLockServiceContext* GetWakeLockServiceContext();
// Notification that the frame wants to go into fullscreen mode.
// |origin| represents the origin of the frame that requests fullscreen.
@@ -209,6 +212,14 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual std::unique_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(
const GURL& url);
+ // Called by |frame| to notify that it has received an update on focused
+ // element. |bounds_in_root_view| is the rectangle containing the element that
+ // is focused and is with respect to root frame's RenderWidgetHost's
+ // coordinate space.
+ virtual void OnFocusedElementChangedInFrame(
+ RenderFrameHostImpl* frame,
+ const gfx::Rect& bounds_in_root_view) {}
+
protected:
virtual ~RenderFrameHostDelegate() {}
};
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.cc b/chromium/content/browser/frame_host/render_frame_host_factory.cc
index cc6d96213ab..f94453e3f67 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.cc
@@ -24,15 +24,18 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create(
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- bool hidden) {
+ bool hidden,
+ bool renderer_initiated_creation) {
if (factory_) {
return factory_->CreateRenderFrameHost(
site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, hidden);
+ frame_tree_node, routing_id, widget_routing_id, hidden,
+ renderer_initiated_creation);
}
return base::WrapUnique(new RenderFrameHostImpl(
site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, hidden));
+ frame_tree_node, routing_id, widget_routing_id, hidden,
+ renderer_initiated_creation));
}
// static
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.h b/chromium/content/browser/frame_host/render_frame_host_factory.h
index 52bef4ad0d6..5fd70cb0d36 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.h
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.h
@@ -38,7 +38,8 @@ class CONTENT_EXPORT RenderFrameHostFactory {
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- bool hidden);
+ bool hidden,
+ bool renderer_initiated_creation);
// Returns true if there is currently a globally-registered factory.
static bool has_factory() { return !!factory_; }
@@ -58,7 +59,8 @@ class CONTENT_EXPORT RenderFrameHostFactory {
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- bool hidden) = 0;
+ bool hidden,
+ bool renderer_initiated_creation) = 0;
// Registers a factory to be called when new RenderFrameHostImpls are created.
// We have only one global factory, so there must be no factory registered
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 ce1cfe711c9..5209ceeb3ed 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -20,11 +21,11 @@
#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"
+#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/download/mhtml_generation_manager.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -37,12 +38,13 @@
#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/resource_dispatcher_host_impl.h"
-#include "content/browser/media/android/media_session_service_impl.h"
+#include "content/browser/media/session/media_session_service_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/browser/presentation/presentation_service_impl.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/browser/renderer_host/media/media_devices_dispatcher_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
@@ -51,7 +53,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/shared_worker/shared_worker_service_impl.h"
-#include "content/browser/wake_lock/wake_lock_service_context.h"
#include "content/browser/websockets/websocket_manager.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/accessibility_messages.h"
@@ -75,48 +76,58 @@
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/browser_side_navigation_policy.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/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "device/generic_sensor/sensor_provider_impl.h"
#include "device/geolocation/geolocation_service_context.h"
#include "device/vibration/vibration_manager_impl.h"
+#include "device/wake_lock/wake_lock_service_context.h"
+#include "media/base/media_switches.h"
+#include "media/media_features.h"
#include "media/mojo/interfaces/media_service.mojom.h"
-#include "media/mojo/interfaces/service_factory.mojom.h"
+#include "media/mojo/interfaces/remoting.mojom.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "services/shell/public/cpp/connector.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/WebKit/public/platform/modules/shapedetection/shapedetection.mojom.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/gfx/geometry/quad_f.h"
#include "url/gurl.h"
#if defined(OS_ANDROID)
+#include "content/browser/android/app_web_message_port_message_filter.h"
#include "content/public/browser/android/java_interfaces.h"
-#if defined(ENABLE_MOJO_CDM)
-#include "content/browser/media/android/provision_fetcher_impl.h"
-#endif
+#include "content/browser/media/android/media_player_renderer.h"
+#include "media/base/audio_renderer_sink.h"
+#include "media/base/video_renderer_sink.h"
+#include "media/mojo/services/mojo_renderer_service.h" // nogncheck
#endif
#if defined(OS_MACOSX)
#include "content/browser/frame_host/popup_menu_helper_mac.h"
#endif
-#if defined(ENABLE_WEBVR)
-#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
-#include "device/vr/vr_service_impl.h" // nogncheck
+#if defined(ENABLE_MOJO_CDM)
+#include "content/public/browser/provision_fetcher_impl.h"
#endif
+#include "device/vr/vr_service_impl.h" // nogncheck
+
using base::TimeDelta;
namespace content {
@@ -193,6 +204,45 @@ void NotifyRenderFrameDetachedOnIO(int render_process_id, int render_frame_id) {
render_frame_id);
}
+#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
+// RemoterFactory that delegates Create() calls to the ContentBrowserClient.
+//
+// Since Create() could be called at any time, perhaps by a stray task being run
+// after a RenderFrameHost has been destroyed, the RemoterFactoryImpl uses the
+// process/routing IDs as a weak reference to the RenderFrameHostImpl.
+class RemoterFactoryImpl final : public media::mojom::RemoterFactory {
+ public:
+ RemoterFactoryImpl(int process_id, int routing_id)
+ : process_id_(process_id), routing_id_(routing_id) {}
+
+ static void Bind(int process_id, int routing_id,
+ media::mojom::RemoterFactoryRequest request) {
+ mojo::MakeStrongBinding(
+ base::MakeUnique<RemoterFactoryImpl>(process_id, routing_id),
+ std::move(request));
+ }
+
+ private:
+ void Create(media::mojom::RemotingSourcePtr source,
+ media::mojom::RemoterRequest request) final {
+ if (auto* host = RenderFrameHostImpl::FromID(process_id_, routing_id_)) {
+ GetContentClient()->browser()->CreateMediaRemoter(
+ host, std::move(source), std::move(request));
+ }
+ }
+
+ const int process_id_;
+ const int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoterFactoryImpl);
+};
+#endif // BUILDFLAG(ENABLE_MEDIA_REMOTING)
+
+template <typename Interface>
+void IgnoreInterfaceRequest(mojo::InterfaceRequest<Interface> request) {
+ // Intentionally ignore the interface request.
+}
+
} // namespace
// static
@@ -206,7 +256,26 @@ RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
void RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView() {
g_allow_injecting_javascript = true;
}
-#endif
+
+void CreateMediaPlayerRenderer(
+ content::RenderFrameHost* render_frame_host,
+ mojo::InterfaceRequest<media::mojom::Renderer> request) {
+ std::unique_ptr<MediaPlayerRenderer> renderer =
+ base::MakeUnique<MediaPlayerRenderer>(render_frame_host);
+
+ // base::Unretained is safe here because the lifetime of the MediaPlayerRender
+ // is tied to the lifetime of the MojoRendererService.
+ media::MojoRendererService::InitiateSurfaceRequestCB surface_request_cb =
+ base::Bind(&MediaPlayerRenderer::InitiateScopedSurfaceRequest,
+ base::Unretained(renderer.get()));
+
+ media::MojoRendererService::Create(
+ nullptr, // CDMs are not supported.
+ nullptr, // Manages its own audio_sink.
+ nullptr, // Does not use video_sink. See StreamTextureWrapper instead.
+ std::move(renderer), surface_request_cb, std::move(request));
+}
+#endif // defined(OS_ANDROID)
// static
RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id,
@@ -241,7 +310,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- bool hidden)
+ bool hidden,
+ bool renderer_initiated_creation)
: render_view_host_(render_view_host),
delegate_(delegate),
site_instance_(static_cast<SiteInstanceImpl*>(site_instance)),
@@ -268,8 +338,11 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
web_ui_type_(WebUI::kNoWebUI),
pending_web_ui_type_(WebUI::kNoWebUI),
should_reuse_web_ui_(false),
+ has_selection_(false),
last_navigation_lofi_state_(LOFI_UNSPECIFIED),
frame_host_binding_(this),
+ waiting_for_init_(renderer_initiated_creation),
+ has_focused_editable_element_(false),
weak_ptr_factory_(this) {
frame_tree_->AddRenderViewHostRef(render_view_host_);
GetProcess()->AddRoute(routing_id_, this);
@@ -339,18 +412,22 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
// If this RenderFrameHost is swapping with a RenderFrameProxyHost, the
// RenderFrame will already be deleted in the renderer process. Main frame
- // RenderFrames will be cleaned up as part of deleting its RenderView. In all
- // other cases, the RenderFrame should be cleaned up (if it exists).
- if (is_active() && !frame_tree_node_->IsMainFrame() && render_frame_created_)
+ // RenderFrames will be cleaned up as part of deleting its RenderView if the
+ // RenderView isn't in use by other frames. In all other cases, the
+ // RenderFrame should be cleaned up (if it exists).
+ bool will_render_view_clean_up_render_frame =
+ frame_tree_node_->IsMainFrame() && render_view_host_->ref_count() == 1;
+ if (is_active() && render_frame_created_ &&
+ !will_render_view_clean_up_render_frame) {
Send(new FrameMsg_Delete(routing_id_));
+ }
// Null out the swapout timer; in crash dumps this member will be null only if
// the dtor has run. (It may also be null in tests.)
swapout_event_monitor_timeout_.reset();
- for (const auto& iter: visual_state_callbacks_) {
+ for (const auto& iter : visual_state_callbacks_)
iter.second.Run(false);
- }
if (render_widget_host_ &&
render_widget_host_->owned_by_render_frame_host()) {
@@ -498,11 +575,12 @@ RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
return render_view_host_;
}
-shell::InterfaceRegistry* RenderFrameHostImpl::GetInterfaceRegistry() {
+service_manager::InterfaceRegistry*
+RenderFrameHostImpl::GetInterfaceRegistry() {
return interface_registry_.get();
}
-shell::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
+service_manager::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
return remote_interfaces_.get();
}
@@ -528,6 +606,18 @@ RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
return remote_associated_interfaces_.get();
}
+#if defined(OS_ANDROID)
+scoped_refptr<AppWebMessagePortMessageFilter>
+RenderFrameHostImpl::GetAppWebMessagePortMessageFilter(int routing_id) {
+ if (!app_web_message_port_message_filter_) {
+ app_web_message_port_message_filter_ =
+ new AppWebMessagePortMessageFilter(routing_id);
+ GetProcess()->AddFilter(app_web_message_port_message_filter_.get());
+ }
+ return app_web_message_port_message_filter_;
+}
+#endif
+
blink::WebPageVisibilityState RenderFrameHostImpl::GetVisibilityState() {
// Works around the crashes seen in https://crbug.com/501863, where the
// active WebContents from a browser iterator may contain a render frame
@@ -594,7 +684,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_AddMessageToConsole, OnAddMessageToConsole)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidAddMessageToConsole,
+ OnDidAddMessageToConsole)
IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameFocused, OnFrameFocused)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartProvisionalLoad,
@@ -633,7 +724,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnEnforceInsecureRequestPolicy)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateToUniqueOrigin,
OnUpdateToUniqueOrigin)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeSandboxFlags,
OnDidChangeSandboxFlags)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFrameOwnerProperties,
@@ -661,6 +751,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidChangeLoadProgress)
IPC_MESSAGE_HANDLER(FrameHostMsg_SerializeAsMHTMLResponse,
OnSerializeAsMHTMLResponse)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SelectionChanged, OnSelectionChanged)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
#if defined(USE_EXTERNAL_POPUP_MENU)
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
@@ -678,50 +770,9 @@ void RenderFrameHostImpl::OnAssociatedInterfaceRequest(
this, interface_name, std::move(handle));
}
-void RenderFrameHostImpl::AccessibilitySetFocus(int object_id) {
- Send(new AccessibilityMsg_SetFocus(routing_id_, object_id));
-}
-
-void RenderFrameHostImpl::AccessibilityDoDefaultAction(int object_id) {
- Send(new AccessibilityMsg_DoDefaultAction(routing_id_, object_id));
-}
-
-void RenderFrameHostImpl::AccessibilityShowContextMenu(int acc_obj_id) {
- Send(new AccessibilityMsg_ShowContextMenu(routing_id_, acc_obj_id));
-}
-
-void RenderFrameHostImpl::AccessibilityScrollToMakeVisible(
- int acc_obj_id, const gfx::Rect& subfocus) {
- Send(new AccessibilityMsg_ScrollToMakeVisible(
- routing_id_, acc_obj_id, subfocus));
-}
-
-void RenderFrameHostImpl::AccessibilityScrollToPoint(
- int acc_obj_id, const gfx::Point& point) {
- Send(new AccessibilityMsg_ScrollToPoint(
- routing_id_, acc_obj_id, point));
-}
-
-void RenderFrameHostImpl::AccessibilitySetScrollOffset(
- int acc_obj_id, const gfx::Point& offset) {
- Send(new AccessibilityMsg_SetScrollOffset(
- routing_id_, acc_obj_id, offset));
-}
-
-void RenderFrameHostImpl::AccessibilitySetSelection(int anchor_object_id,
- int anchor_offset,
- int focus_object_id,
- int focus_offset) {
- Send(new AccessibilityMsg_SetSelection(routing_id_,
- anchor_object_id,
- anchor_offset,
- focus_object_id,
- focus_offset));
-}
-
-void RenderFrameHostImpl::AccessibilitySetValue(
- int object_id, const base::string16& value) {
- Send(new AccessibilityMsg_SetValue(routing_id_, object_id, value));
+void RenderFrameHostImpl::AccessibilityPerformAction(
+ const ui::AXActionData& action_data) {
+ Send(new AccessibilityMsg_PerformAction(routing_id_, action_data));
}
bool RenderFrameHostImpl::AccessibilityViewHasFocus() const {
@@ -747,14 +798,6 @@ gfx::Point RenderFrameHostImpl::AccessibilityOriginInScreen(
return gfx::Point();
}
-void RenderFrameHostImpl::AccessibilityHitTest(const gfx::Point& point) {
- Send(new AccessibilityMsg_HitTest(routing_id_, point));
-}
-
-void RenderFrameHostImpl::AccessibilitySetAccessibilityFocus(int acc_obj_id) {
- Send(new AccessibilityMsg_SetAccessibilityFocus(routing_id_, acc_obj_id));
-}
-
void RenderFrameHostImpl::AccessibilityReset() {
accessibility_reset_token_ = g_next_accessibility_reset_token++;
Send(new AccessibilityMsg_Reset(routing_id_, accessibility_reset_token_));
@@ -770,7 +813,6 @@ void RenderFrameHostImpl::AccessibilityFatalError() {
Send(new AccessibilityMsg_FatalError(routing_id_));
} else {
accessibility_reset_token_ = g_next_accessibility_reset_token++;
- UMA_HISTOGRAM_COUNTS("Accessibility.FrameResetCount", 1);
Send(new AccessibilityMsg_Reset(routing_id_, accessibility_reset_token_));
}
}
@@ -813,27 +855,35 @@ void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
}
void RenderFrameHostImpl::Create(
- const shell::Identity& remote_identity,
- media::mojom::ServiceFactoryRequest request) {
- std::unique_ptr<shell::InterfaceRegistry> registry(
- new shell::InterfaceRegistry);
-#if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
+ const service_manager::Identity& remote_identity,
+ media::mojom::InterfaceFactoryRequest request) {
+ auto registry = base::MakeUnique<service_manager::InterfaceRegistry>(
+ std::string());
+#if defined(ENABLE_MOJO_CDM)
+ net::URLRequestContextGetter* context_getter =
+ BrowserContext::GetDefaultStoragePartition(
+ GetProcess()->GetBrowserContext())
+ ->GetURLRequestContext();
registry->AddInterface(
- base::Bind(&ProvisionFetcherImpl::Create, this));
-#endif
+ base::Bind(&ProvisionFetcherImpl::Create, context_getter));
+#endif // defined(ENABLE_MOJO_CDM)
GetContentClient()->browser()->ExposeInterfacesToMediaService(registry.get(),
this);
- shell::mojom::InterfaceProviderPtr interfaces;
- registry->Bind(GetProxy(&interfaces));
+ service_manager::mojom::InterfaceProviderPtr interfaces;
+ registry->Bind(GetProxy(&interfaces),
+ service_manager::Identity(),
+ service_manager::InterfaceProviderSpec(),
+ service_manager::Identity(),
+ service_manager::InterfaceProviderSpec());
media_registries_.push_back(std::move(registry));
// TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950.
media::mojom::MediaServicePtr media_service;
- shell::Connector* connector =
+ service_manager::Connector* connector =
ServiceManagerConnection::GetForProcess()->GetConnector();
- connector->ConnectToInterface("service:media", &media_service);
- media_service->CreateServiceFactory(std::move(request),
- std::move(interfaces));
+ connector->ConnectToInterface("media", &media_service);
+ media_service->CreateInterfaceFactory(std::move(request),
+ std::move(interfaces));
}
bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
@@ -883,8 +933,7 @@ bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
params->widget_params->hidden = true;
}
- RenderProcessHostImpl::GetRendererInterface(GetProcess())->CreateFrame(
- std::move(params));
+ GetProcess()->GetRendererInterface()->CreateFrame(std::move(params));
// The RenderWidgetHost takes ownership of its view. It is tied to the
// lifetime of the current RenderProcessHost for this RenderFrameHost.
@@ -921,10 +970,12 @@ void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
// If the current status is different than the new status, the delegate
// needs to be notified.
if (delegate_ && (created != was_created)) {
- if (created)
+ if (created) {
+ SetUpMojoIfNeeded();
delegate_->RenderFrameCreated(this);
- else
+ } else {
delegate_->RenderFrameDeleted(this);
+ }
}
if (created && render_widget_host_)
@@ -933,14 +984,24 @@ void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
void RenderFrameHostImpl::Init() {
ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI(this);
+ if (!waiting_for_init_)
+ return;
+
+ waiting_for_init_ = false;
+ if (pendinging_navigate_) {
+ frame_tree_node()->navigator()->OnBeginNavigation(
+ frame_tree_node(), pendinging_navigate_->first,
+ pendinging_navigate_->second);
+ pendinging_navigate_.reset();
+ }
}
-void RenderFrameHostImpl::OnAddMessageToConsole(
+void RenderFrameHostImpl::OnDidAddMessageToConsole(
int32_t level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
- if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
+ if (delegate_->DidAddMessageToConsole(level, message, line_no, source_id))
return;
// Pass through log level only on WebUI pages to limit console spew.
@@ -992,17 +1053,27 @@ void RenderFrameHostImpl::OnFrameFocused() {
}
void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
+ GURL validated_url(params.url);
+ GetProcess()->FilterURL(false, &validated_url);
+
if (params.is_history_navigation_in_new_child) {
DCHECK(SiteIsolationPolicy::UseSubframeNavigationEntries());
// Try to find a FrameNavigationEntry that matches this frame instead, based
// on the frame's unique name. If this can't be found, fall back to the
- // default params using OpenURL below.
- if (frame_tree_node_->navigator()->NavigateNewChildFrame(this, params.url))
+ // default params using RequestOpenURL below.
+ if (frame_tree_node_->navigator()->NavigateNewChildFrame(this,
+ validated_url))
return;
}
- OpenURL(params, GetSiteInstance());
+ TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
+ validated_url.possibly_invalid_spec());
+
+ frame_tree_node_->navigator()->RequestOpenURL(
+ this, validated_url, params.uses_post, params.resource_request_body,
+ params.extra_headers, params.referrer, params.disposition,
+ params.should_replace_current_entry, params.user_gesture);
}
void RenderFrameHostImpl::OnCancelInitialHistoryLoad() {
@@ -1038,6 +1109,11 @@ void RenderFrameHostImpl::OnDocumentOnLoadCompleted(
void RenderFrameHostImpl::OnDidStartProvisionalLoad(
const GURL& url,
const base::TimeTicks& navigation_start) {
+ // TODO(clamy): Check if other navigation methods (OpenURL,
+ // DidFailProvisionalLoad, ...) should also be ignored if the RFH is no longer
+ // active.
+ if (!is_active())
+ return;
frame_tree_node_->navigator()->DidStartProvisionalLoad(this, url,
navigation_start);
}
@@ -1072,12 +1148,6 @@ void RenderFrameHostImpl::OnDidFailLoadWithError(
// Called when the renderer navigates. For every frame loaded, we'll get this
// notification containing parameters identifying the navigation.
-//
-// Subframes are identified by the page transition type. For subframes loaded
-// as part of a wider page load, the page_id will be the same as for the top
-// level frame. If the user explicitly requests a subframe navigation, we will
-// get a new page_id because we need to create a new navigation entry for that
-// action.
void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
ScopedCommitStateResetter commit_state_resetter(this);
RenderProcessHost* process = GetProcess();
@@ -1178,68 +1248,44 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
return;
}
- // If the URL does not match what the NavigationHandle expects, treat the
- // commit as a new navigation. This can happen if an ongoing slow
- // same-process navigation is interrupted by a synchronous renderer-initiated
- // navigation.
- // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get
- // reset here, because the NavigationHandle tracks the URL but the
- // validated_params.url tracks the data. The trick of saving the old entry ids
- // for these navigations should go away when this is properly handled. See
- // crbug.com/588317.
- int entry_id_for_data_nav = 0;
- bool is_renderer_initiated = true;
- if (navigation_handle_ &&
- (navigation_handle_->GetURL() != validated_params.url)) {
- // Make sure that the pending entry was really loaded via
- // LoadDataWithBaseURL and that it matches this handle.
- NavigationEntryImpl* pending_entry =
- NavigationEntryImpl::FromNavigationEntry(
- frame_tree_node()->navigator()->GetController()->GetPendingEntry());
- bool pending_entry_matches_handle =
- pending_entry &&
- pending_entry->GetUniqueID() ==
- navigation_handle_->pending_nav_entry_id();
- // TODO(csharrison): The pending entry's base url should equal
- // |validated_params.base_url|. This is not the case for loads with invalid
- // base urls.
- if (navigation_handle_->GetURL() == validated_params.base_url &&
- pending_entry_matches_handle &&
- !pending_entry->GetBaseURLForDataURL().is_empty()) {
- entry_id_for_data_nav = navigation_handle_->pending_nav_entry_id();
- is_renderer_initiated = pending_entry->is_renderer_initiated();
+ // PlzNavigate
+ if (!navigation_handle_ && IsBrowserSideNavigationEnabled()) {
+ // PlzNavigate: the browser has not been notified about the start of the
+ // load in this renderer yet (e.g., for same-page navigations that start in
+ // the renderer). Do it now.
+ if (!is_loading()) {
+ bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
+ is_loading_ = true;
+ frame_tree_node()->DidStartLoading(true, was_loading);
}
- navigation_handle_.reset();
+ pending_commit_ = false;
}
- // Synchronous renderer-initiated navigations will send a
- // DidCommitProvisionalLoad IPC without a prior DidStartProvisionalLoad
- // message.
- if (!navigation_handle_) {
- // There is no pending NavigationEntry in these cases, so pass 0 as the
- // nav_id. If the previous handle was a prematurely aborted navigation
- // loaded via LoadDataWithBaseURL, propogate the entry id.
- navigation_handle_ = NavigationHandleImpl::Create(
- validated_params.url, frame_tree_node_, is_renderer_initiated,
- true, // is_synchronous
- validated_params.is_srcdoc, base::TimeTicks::Now(),
- entry_id_for_data_nav,
- false); // started_from_context_menu
- // PlzNavigate
- if (IsBrowserSideNavigationEnabled()) {
- // PlzNavigate: synchronous loads happen in the renderer, and the browser
- // has not been notified about the start of the load yet. Do it now.
- if (!is_loading()) {
- bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
- is_loading_ = true;
- frame_tree_node()->DidStartLoading(true, was_loading);
- }
- pending_commit_ = false;
- }
+ // Find the appropriate NavigationHandle for this navigation.
+ std::unique_ptr<NavigationHandleImpl> navigation_handle =
+ TakeNavigationHandleForCommit(validated_params);
+ DCHECK(navigation_handle);
+
+ // PlzNavigate sends searchable form data in the BeginNavigation message
+ // while non-PlzNavigate sends it in the DidCommitProvisionalLoad message.
+ // Update |navigation_handle| if necessary.
+ if (!IsBrowserSideNavigationEnabled() &&
+ !validated_params.searchable_form_url.is_empty()) {
+ navigation_handle->set_searchable_form_url(
+ validated_params.searchable_form_url);
+ navigation_handle->set_searchable_form_encoding(
+ validated_params.searchable_form_encoding);
+
+ // Reset them so that they are consistent in both the PlzNavigate and
+ // non-PlzNavigate case. Users should use those values from
+ // NavigationHandle.
+ validated_params.searchable_form_url = GURL();
+ validated_params.searchable_form_encoding = std::string();
}
accessibility_reset_count_ = 0;
- frame_tree_node()->navigator()->DidNavigate(this, validated_params);
+ frame_tree_node()->navigator()->DidNavigate(this, validated_params,
+ std::move(navigation_handle));
// Since we didn't early return, it's safe to keep the commit state.
commit_state_resetter.disable();
@@ -1299,8 +1345,12 @@ int RenderFrameHostImpl::GetEnabledBindings() {
void RenderFrameHostImpl::SetNavigationHandle(
std::unique_ptr<NavigationHandleImpl> navigation_handle) {
navigation_handle_ = std::move(navigation_handle);
- if (navigation_handle_)
- navigation_handle_->set_render_frame_host(this);
+
+ // TODO(clamy): Remove this debug code once we understand better how we get to
+ // the point of attempting to transfer a navigation from a RFH that is no
+ // longer active.
+ if (navigation_handle_ && !is_active())
+ base::debug::DumpWithoutCrashing();
}
std::unique_ptr<NavigationHandleImpl>
@@ -1311,20 +1361,6 @@ RenderFrameHostImpl::PassNavigationHandleOwnership() {
return std::move(navigation_handle_);
}
-void RenderFrameHostImpl::OnCrossSiteResponse(
- const GlobalRequestID& global_request_id,
- std::unique_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request,
- const std::vector<GURL>& transfer_url_chain,
- const Referrer& referrer,
- ui::PageTransition page_transition,
- bool should_replace_current_entry) {
- frame_tree_node_->render_manager()->OnCrossSiteResponse(
- this, global_request_id, std::move(cross_site_transferring_request),
- transfer_url_chain, referrer, page_transition,
- should_replace_current_entry);
-}
-
void RenderFrameHostImpl::SwapOut(
RenderFrameProxyHost* proxy,
bool is_loading) {
@@ -1546,6 +1582,15 @@ void RenderFrameHostImpl::DisableSwapOutTimerForTesting() {
swapout_event_monitor_timeout_.reset();
}
+void RenderFrameHostImpl::OnRendererConnect(
+ const service_manager::ServiceInfo& local_info,
+ const service_manager::ServiceInfo& remote_info) {
+ if (remote_info.identity.name() != mojom::kRendererServiceName)
+ return;
+ browser_info_ = local_info;
+ renderer_info_ = remote_info;
+}
+
void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
// Validate the URLs in |params|. If the renderer can't request the URLs
// directly, don't show them in the context menu.
@@ -1717,12 +1762,6 @@ void RenderFrameHostImpl::OnUpdateToUniqueOrigin(
is_potentially_trustworthy_unique_origin);
}
-void RenderFrameHostImpl::OnDidAssignPageId(int32_t page_id) {
- // Update the RVH's current page ID so that future IPCs from the renderer
- // correspond to the new page.
- render_view_host_->page_id_ = page_id;
-}
-
FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild(
int32_t child_frame_routing_id,
bad_message::BadMessageReason reason) {
@@ -1787,9 +1826,8 @@ void RenderFrameHostImpl::OnUpdateTitle(
return;
}
- delegate_->UpdateTitle(this, render_view_host_->page_id_, title,
- WebTextDirectionToChromeTextDirection(
- title_direction));
+ delegate_->UpdateTitle(
+ this, title, WebTextDirectionToChromeTextDirection(title_direction));
}
void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
@@ -1802,10 +1840,22 @@ void RenderFrameHostImpl::OnBeginNavigation(
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params) {
CHECK(IsBrowserSideNavigationEnabled());
+ if (!is_active())
+ return;
CommonNavigationParams validated_params = common_params;
GetProcess()->FilterURL(false, &validated_params.url);
+
+ BeginNavigationParams validated_begin_params = begin_params;
+ GetProcess()->FilterURL(true, &validated_begin_params.searchable_form_url);
+
+ if (waiting_for_init_) {
+ pendinging_navigate_ = base::MakeUnique<PendingNavigation>(
+ validated_params, validated_begin_params);
+ return;
+ }
+
frame_tree_node()->navigator()->OnBeginNavigation(
- frame_tree_node(), validated_params, begin_params);
+ frame_tree_node(), validated_params, validated_begin_params);
}
void RenderFrameHostImpl::OnDispatchLoad() {
@@ -2099,6 +2149,27 @@ void RenderFrameHostImpl::OnSerializeAsMHTMLResponse(
renderer_main_thread_time);
}
+void RenderFrameHostImpl::OnSelectionChanged(const base::string16& text,
+ uint32_t offset,
+ const gfx::Range& range) {
+ has_selection_ = !text.empty();
+ GetRenderWidgetHost()->SelectionChanged(text, offset, range);
+}
+
+void RenderFrameHostImpl::OnFocusedNodeChanged(
+ bool is_editable_element,
+ const gfx::Rect& bounds_in_frame_widget) {
+ if (!GetView())
+ return;
+
+ has_focused_editable_element_ = is_editable_element;
+ // First convert the bounds to root view.
+ delegate_->OnFocusedElementChangedInFrame(
+ this, gfx::Rect(GetView()->TransformPointToRootCoordSpace(
+ bounds_in_frame_widget.origin()),
+ bounds_in_frame_widget.size()));
+}
+
#if defined(USE_EXTERNAL_POPUP_MENU)
void RenderFrameHostImpl::OnShowPopup(
const FrameHostMsg_ShowPopup_Params& params) {
@@ -2146,14 +2217,14 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
weak_ptr_factory_.GetWeakPtr())));
}
- WakeLockServiceContext* wake_lock_service_context =
+ device::WakeLockServiceContext* wake_lock_service_context =
delegate_ ? delegate_->GetWakeLockServiceContext() : nullptr;
if (wake_lock_service_context) {
// WakeLockServiceContext is owned by WebContentsImpl so it will outlive
// this RenderFrameHostImpl, hence a raw pointer can be bound to service
// factory callback.
- GetInterfaceRegistry()->AddInterface<blink::mojom::WakeLockService>(
- base::Bind(&WakeLockServiceContext::CreateService,
+ GetInterfaceRegistry()->AddInterface<device::mojom::WakeLockService>(
+ base::Bind(&device::WakeLockServiceContext::CreateService,
base::Unretained(wake_lock_service_context)));
}
@@ -2167,30 +2238,33 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
GetInterfaceRegistry()->AddInterface(base::Bind(
&PresentationServiceImpl::CreateMojoService, base::Unretained(this)));
+ GetInterfaceRegistry()->AddInterface(
+ base::Bind(&MediaSessionServiceImpl::Create, base::Unretained(this)));
+
#if defined(OS_ANDROID)
GetInterfaceRegistry()->AddInterface(
GetGlobalJavaInterfaces()
- ->CreateInterfaceFactory<device::VibrationManager>());
+ ->CreateInterfaceFactory<blink::mojom::ShapeDetection>());
+
GetInterfaceRegistry()->AddInterface(
- base::Bind(&MediaSessionServiceImpl::Create, base::Unretained(this)));
+ GetGlobalJavaInterfaces()
+ ->CreateInterfaceFactory<device::VibrationManager>());
+
+ if (base::FeatureList::IsEnabled(media::kAndroidMediaPlayerRenderer)) {
+ // Creates a MojoRendererService, passing it a MediaPlayerRender.
+ GetInterfaceRegistry()->AddInterface<media::mojom::Renderer>(base::Bind(
+ &content::CreateMediaPlayerRenderer, base::Unretained(this)));
+ }
#else
GetInterfaceRegistry()->AddInterface(
base::Bind(&device::VibrationManagerImpl::Create));
-#endif
-
- bool enable_web_bluetooth = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWebBluetooth);
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_MACOSX)
- enable_web_bluetooth = true;
-#endif
+#endif // defined(OS_ANDROID)
- if (enable_web_bluetooth) {
- GetInterfaceRegistry()->AddInterface(base::Bind(
- base::IgnoreResult(&RenderFrameHostImpl::CreateWebBluetoothService),
- base::Unretained(this)));
- }
+ GetInterfaceRegistry()->AddInterface(base::Bind(
+ base::IgnoreResult(&RenderFrameHostImpl::CreateWebBluetoothService),
+ base::Unretained(this)));
- GetInterfaceRegistry()->AddInterface<media::mojom::ServiceFactory>(this);
+ GetInterfaceRegistry()->AddInterface<media::mojom::InterfaceFactory>(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
@@ -2201,20 +2275,44 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
routing_id_));
#if defined(ENABLE_WEBVR)
- const base::CommandLine& browser_command_line =
- *base::CommandLine::ForCurrentProcess();
+ GetInterfaceRegistry()->AddInterface<device::mojom::VRService>(
+ base::Bind(&device::VRServiceImpl::BindRequest));
+#else
+ GetInterfaceRegistry()->AddInterface<device::mojom::VRService>(
+ base::Bind(&IgnoreInterfaceRequest<device::mojom::VRService>));
+#endif
- if (browser_command_line.HasSwitch(switches::kEnableWebVR)) {
- GetInterfaceRegistry()->AddInterface<device::VRService>(
- base::Bind(&device::VRServiceImpl::BindRequest));
+ if (base::FeatureList::IsEnabled(features::kGenericSensor)) {
+ GetInterfaceRegistry()->AddInterface(
+ base::Bind(&device::SensorProviderImpl::Create,
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
}
-#endif
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableGenericSensors)) {
+
+#if defined(ENABLE_WEBRTC)
+ // BrowserMainLoop::GetInstance() may be null on unit tests.
+ if (BrowserMainLoop::GetInstance()) {
+ // BrowserMainLoop, which owns MediaStreamManager, is alive for the lifetime
+ // of Mojo communication (see BrowserMainLoop::ShutdownThreadsAndCleanUp(),
+ // which shuts down Mojo). Hence, passing that MediaStreamManager instance
+ // as a raw pointer here is safe.
+ MediaStreamManager* media_stream_manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
GetInterfaceRegistry()->AddInterface(
- base::Bind(&device::SensorProviderImpl::Create),
+ base::Bind(&MediaDevicesDispatcherHost::Create, GetProcess()->GetID(),
+ GetRoutingID(), GetProcess()
+ ->GetBrowserContext()
+ ->GetResourceContext()
+ ->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()));
+#endif // BUILDFLAG(ENABLE_MEDIA_REMOTING)
GetContentClient()->browser()->RegisterRenderFrameMojoInterfaces(
GetInterfaceRegistry(), this);
@@ -2333,19 +2431,6 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
}
}
-void RenderFrameHostImpl::OpenURL(const FrameHostMsg_OpenURL_Params& params,
- SiteInstance* source_site_instance) {
- GURL validated_url(params.url);
- GetProcess()->FilterURL(false, &validated_url);
-
- TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
- validated_url.possibly_invalid_spec());
- frame_tree_node_->navigator()->RequestOpenURL(
- this, validated_url, params.uses_post, params.resource_request_body,
- source_site_instance, params.referrer, params.disposition,
- params.should_replace_current_entry, params.user_gesture);
-}
-
void RenderFrameHostImpl::Stop() {
Send(new FrameMsg_Stop(routing_id_));
}
@@ -2388,14 +2473,22 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation,
// handler.
is_waiting_for_beforeunload_ack_ = true;
unload_ack_is_for_navigation_ = for_navigation;
- // Increment the in-flight event count, to ensure that input events won't
- // cancel the timeout timer.
- render_view_host_->GetWidget()->increment_in_flight_event_count();
- render_view_host_->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD);
- send_before_unload_start_time_ = base::TimeTicks::Now();
- Send(new FrameMsg_BeforeUnload(routing_id_, is_reload));
+ if (render_view_host_->GetDelegate()->IsJavaScriptDialogShowing()) {
+ // If there is a JavaScript dialog up, don't bother sending the renderer
+ // the unload event because it is known unresponsive, waiting for the
+ // reply from the dialog.
+ SimulateBeforeUnloadAck();
+ } else {
+ // Increment the in-flight event count, to ensure that input events won't
+ // cancel the timeout timer.
+ render_view_host_->GetWidget()->increment_in_flight_event_count();
+ render_view_host_->GetWidget()->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS),
+ blink::WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD);
+ send_before_unload_start_time_ = base::TimeTicks::Now();
+ Send(new FrameMsg_BeforeUnload(routing_id_, is_reload));
+ }
}
}
@@ -2428,15 +2521,15 @@ void RenderFrameHostImpl::SetFocusedFrame() {
Send(new FrameMsg_SetFocusedFrame(routing_id_));
}
-void RenderFrameHostImpl::ClearFocusedFrame() {
- Send(new FrameMsg_ClearFocusedFrame(routing_id_));
-}
-
void RenderFrameHostImpl::ExtendSelectionAndDelete(size_t before,
size_t after) {
Send(new InputMsg_ExtendSelectionAndDelete(routing_id_, before, after));
}
+void RenderFrameHostImpl::DeleteSurroundingText(size_t before, size_t after) {
+ Send(new InputMsg_DeleteSurroundingText(routing_id_, before, after));
+}
+
void RenderFrameHostImpl::JavaScriptDialogClosed(
IPC::Message* reply_msg,
bool success,
@@ -2450,18 +2543,18 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
// leave the current page. In this case, use the regular timeout value used
// during the (before)unload handling.
if (is_waiting) {
- RenderWidgetHostDelegate::RendererUnresponsiveType type =
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_DIALOG_CLOSED;
+ RendererUnresponsiveType type =
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_DIALOG_CLOSED;
if (success) {
type = is_waiting_for_beforeunload_ack_
- ? RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD
- : RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNLOAD;
+ ? RendererUnresponsiveType::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD
+ : RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNLOAD;
}
render_view_host_->GetWidget()->StartHangMonitorTimeout(
success
? TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)
: render_view_host_->GetWidget()->hung_renderer_delay(),
- type);
+ blink::WebInputEvent::Undefined, type);
}
FrameHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
@@ -2477,7 +2570,7 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
if (is_waiting && dialog_was_suppressed) {
render_view_host_->GetWidget()->delegate()->RendererUnresponsive(
render_view_host_->GetWidget(),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_DIALOG_SUPPRESSED);
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_DIALOG_SUPPRESSED);
}
}
@@ -2555,7 +2648,20 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
if (interface_registry_.get())
return;
- interface_registry_.reset(new shell::InterfaceRegistry);
+ interface_registry_ = base::MakeUnique<service_manager::InterfaceRegistry>(
+ mojom::kNavigation_FrameSpec);
+
+ ServiceManagerConnection* service_manager_connection =
+ BrowserContext::GetServiceManagerConnectionFor(
+ GetProcess()->GetBrowserContext());
+ // |service_manager_connection| may not be set in unit tests using
+ // TestBrowserContext.
+ if (service_manager_connection) {
+ on_connect_handler_id_ = service_manager_connection->AddOnConnectHandler(
+ base::Bind(&RenderFrameHostImpl::OnRendererConnect,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
if (!GetProcess()->GetRemoteInterfaces())
return;
@@ -2565,17 +2671,26 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
frame_factory->CreateFrame(routing_id_, GetProxy(&frame_),
frame_host_binding_.CreateInterfacePtrAndBind());
-
- shell::mojom::InterfaceProviderPtr remote_interfaces;
- shell::mojom::InterfaceProviderRequest remote_interfaces_request =
+ service_manager::mojom::InterfaceProviderPtr remote_interfaces;
+ service_manager::mojom::InterfaceProviderRequest remote_interfaces_request =
GetProxy(&remote_interfaces);
- remote_interfaces_.reset(new shell::InterfaceProvider);
+ remote_interfaces_.reset(new service_manager::InterfaceProvider);
remote_interfaces_->Bind(std::move(remote_interfaces));
frame_->GetInterfaceProvider(std::move(remote_interfaces_request));
}
void RenderFrameHostImpl::InvalidateMojoConnection() {
interface_registry_.reset();
+
+ ServiceManagerConnection* service_manager_connection =
+ BrowserContext::GetServiceManagerConnectionFor(
+ GetProcess()->GetBrowserContext());
+ // |service_manager_connection| may be null in tests using TestBrowserContext.
+ if (service_manager_connection) {
+ service_manager_connection->RemoveOnConnectHandler(on_connect_handler_id_);
+ on_connect_handler_id_ = 0;
+ }
+
frame_.reset();
frame_host_binding_.Close();
@@ -2704,6 +2819,15 @@ void RenderFrameHostImpl::SuppressFurtherDialogs() {
Send(new FrameMsg_SuppressFurtherDialogs(GetRoutingID()));
}
+void RenderFrameHostImpl::SetHasReceivedUserGesture() {
+ Send(new FrameMsg_SetHasReceivedUserGesture(GetRoutingID()));
+}
+
+void RenderFrameHostImpl::ClearFocusedElement() {
+ has_focused_editable_element_ = false;
+ Send(new FrameMsg_ClearFocusedElement(GetRoutingID()));
+}
+
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
@@ -2769,10 +2893,6 @@ BrowserAccessibilityManager*
bool is_root_frame = !frame_tree_node()->parent();
browser_accessibility_manager_.reset(
view->CreateBrowserAccessibilityManager(this, is_root_frame));
- if (browser_accessibility_manager_)
- UMA_HISTOGRAM_COUNTS("Accessibility.FrameEnabledCount", 1);
- else
- UMA_HISTOGRAM_COUNTS("Accessibility.FrameDidNotEnableCount", 1);
}
return browser_accessibility_manager_.get();
}
@@ -2838,9 +2958,23 @@ void RenderFrameHostImpl::FilesSelectedInChooser(
Send(new FrameMsg_RunFileChooserResponse(routing_id_, files));
}
+bool RenderFrameHostImpl::HasSelection() {
+ return has_selection_;
+}
+
void RenderFrameHostImpl::GetInterfaceProvider(
- shell::mojom::InterfaceProviderRequest interfaces) {
- interface_registry_->Bind(std::move(interfaces));
+ service_manager::mojom::InterfaceProviderRequest interfaces) {
+ service_manager::InterfaceProviderSpec browser_spec, renderer_spec;
+ // TODO(beng): CHECK these return true.
+ service_manager::GetInterfaceProviderSpec(
+ mojom::kNavigation_FrameSpec, browser_info_.interface_provider_specs,
+ &browser_spec);
+ service_manager::GetInterfaceProviderSpec(
+ mojom::kNavigation_FrameSpec, renderer_info_.interface_provider_specs,
+ &renderer_spec);
+ interface_registry_->Bind(std::move(interfaces),
+ browser_info_.identity, browser_spec,
+ renderer_info_.identity, renderer_spec);
}
#if defined(USE_EXTERNAL_POPUP_MENU)
@@ -3120,4 +3254,88 @@ void RenderFrameHostImpl::DeleteWebBluetoothService() {
web_bluetooth_service_.reset();
}
+std::unique_ptr<NavigationHandleImpl>
+RenderFrameHostImpl::TakeNavigationHandleForCommit(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
+ // If this is a same-page navigation, there isn't an existing NavigationHandle
+ // to use for the navigation. Create one, but don't reset any NavigationHandle
+ // tracking an ongoing navigation, since this may lead to the cancellation of
+ // the navigation.
+ if (params.was_within_same_page) {
+ // We don't ever expect navigation_handle_ to match, because handles are not
+ // created for same-page navigations.
+ DCHECK(!navigation_handle_ || !navigation_handle_->IsSamePage());
+
+ // First, determine if the navigation corresponds to the pending navigation
+ // entry. This is the case for a browser-initiated same-page navigation,
+ // which does not cause a NavigationHandle to be created because it does not
+ // go through DidStartProvisionalLoad.
+ bool is_renderer_initiated = true;
+ int pending_nav_entry_id = 0;
+ NavigationEntryImpl* pending_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ frame_tree_node()->navigator()->GetController()->GetPendingEntry());
+ if (pending_entry && pending_entry->GetUniqueID() == params.nav_entry_id) {
+ pending_nav_entry_id = params.nav_entry_id;
+ is_renderer_initiated = pending_entry->is_renderer_initiated();
+ }
+
+ return NavigationHandleImpl::Create(
+ params.url, frame_tree_node_, is_renderer_initiated,
+ params.was_within_same_page, params.is_srcdoc, base::TimeTicks::Now(),
+ pending_nav_entry_id, false); // started_from_context_menu
+ }
+
+ // Determine if the current NavigationHandle can be used.
+ if (navigation_handle_ && navigation_handle_->GetURL() == params.url) {
+ return std::move(navigation_handle_);
+ }
+
+ // If the URL does not match what the NavigationHandle expects, treat the
+ // commit as a new navigation. This can happen when loading a Data
+ // navigation with LoadDataWithBaseURL.
+ //
+ // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get
+ // reset here, because the NavigationHandle tracks the URL but the params.url
+ // tracks the data. The trick of saving the old entry ids for these
+ // navigations should go away when this is properly handled.
+ // See crbug.com/588317.
+ int entry_id_for_data_nav = 0;
+ bool is_renderer_initiated = true;
+
+ // Make sure that the pending entry was really loaded via LoadDataWithBaseURL
+ // and that it matches this handle. TODO(csharrison): The pending entry's
+ // base url should equal |params.base_url|. This is not the case for loads
+ // with invalid base urls.
+ if (navigation_handle_) {
+ NavigationEntryImpl* pending_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ frame_tree_node()->navigator()->GetController()->GetPendingEntry());
+ bool pending_entry_matches_handle =
+ pending_entry &&
+ pending_entry->GetUniqueID() ==
+ navigation_handle_->pending_nav_entry_id();
+ // TODO(csharrison): The pending entry's base url should equal
+ // |validated_params.base_url|. This is not the case for loads with invalid
+ // base urls.
+ if (navigation_handle_->GetURL() == params.base_url &&
+ pending_entry_matches_handle &&
+ !pending_entry->GetBaseURLForDataURL().is_empty()) {
+ entry_id_for_data_nav = navigation_handle_->pending_nav_entry_id();
+ is_renderer_initiated = pending_entry->is_renderer_initiated();
+ }
+
+ // Reset any existing NavigationHandle.
+ navigation_handle_.reset();
+ }
+
+ // There is no pending NavigationEntry in these cases, so pass 0 as the
+ // pending_nav_entry_id. If the previous handle was a prematurely aborted
+ // navigation loaded via LoadDataWithBaseURL, propagate the entry id.
+ return NavigationHandleImpl::Create(
+ params.url, frame_tree_node_, is_renderer_initiated,
+ params.was_within_same_page, params.is_srcdoc, base::TimeTicks::Now(),
+ entry_id_for_data_nav, false); // started_from_context_menu
+}
+
} // 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 8b275095cde..f0f8bc3a096 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -36,10 +36,10 @@
#include "content/common/navigation_params.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/javascript_message_type.h"
-#include "media/mojo/interfaces/service_factory.mojom.h"
+#include "media/mojo/interfaces/interface_factory.mojom.h"
#include "net/http/http_response_headers.h"
-#include "services/shell/public/cpp/interface_factory.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_factory.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
#include "third_party/WebKit/public/web/WebTreeScopeType.h"
@@ -50,6 +50,7 @@ class GURL;
struct AccessibilityHostMsg_EventParams;
struct AccessibilityHostMsg_FindInPageResultParams;
struct AccessibilityHostMsg_LocationChangeParams;
+struct FrameHostMsg_DidCommitProvisionalLoad_Params;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
struct FrameHostMsg_OpenURL_Params;
struct FrameMsg_TextTrackSettings_Params;
@@ -58,7 +59,6 @@ struct FrameHostMsg_ShowPopup_Params;
#endif
namespace base {
-class FilePath;
class ListValue;
}
@@ -68,11 +68,14 @@ class WebBluetoothService;
}
}
-namespace content {
+namespace gfx {
+class Range;
+}
+namespace content {
+class AppWebMessagePortMessageFilter;
class AssociatedInterfaceProviderImpl;
class CrossProcessFrameConnector;
-class CrossSiteTransferringRequest;
class FrameTree;
class FrameTreeNode;
class NavigationHandleImpl;
@@ -93,9 +96,7 @@ struct ContentSecurityPolicyHeader;
struct ContextMenuParams;
struct FileChooserParams;
struct FrameOwnerProperties;
-struct GlobalRequestID;
struct FileChooserParams;
-struct Referrer;
struct ResourceResponse;
class CONTENT_EXPORT RenderFrameHostImpl
@@ -104,7 +105,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
public BrowserAccessibilityDelegate,
public SiteInstanceImpl::Observer,
public NON_EXPORTED_BASE(
- shell::InterfaceFactory<media::mojom::ServiceFactory>) {
+ service_manager::InterfaceFactory<media::mojom::InterfaceFactory>) {
public:
using AXTreeSnapshotCallback =
base::Callback<void(
@@ -154,21 +155,22 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CopyImageAt(int x, int y) override;
void SaveImageAt(int x, int y) override;
RenderViewHost* GetRenderViewHost() override;
- shell::InterfaceRegistry* GetInterfaceRegistry() override;
- shell::InterfaceProvider* GetRemoteInterfaces() override;
+ service_manager::InterfaceRegistry* GetInterfaceRegistry() override;
+ service_manager::InterfaceProvider* GetRemoteInterfaces() override;
AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
blink::WebPageVisibilityState GetVisibilityState() override;
bool IsRenderFrameLive() override;
int GetProxyCount() override;
void FilesSelectedInChooser(const std::vector<FileChooserFileInfo>& files,
FileChooserParams::Mode permissions) override;
+ bool HasSelection() override;
void RequestTextSurroundingSelection(
const TextSurroundingSelectionCallback& callback,
int max_length) override;
// mojom::FrameHost
void GetInterfaceProvider(
- shell::mojom::InterfaceProviderRequest interfaces) override;
+ service_manager::mojom::InterfaceProviderRequest interfaces) override;
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -180,27 +182,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
mojo::ScopedInterfaceEndpointHandle handle) override;
// BrowserAccessibilityDelegate
- void AccessibilitySetFocus(int acc_obj_id) override;
- void AccessibilityDoDefaultAction(int acc_obj_id) override;
- void AccessibilityShowContextMenu(int acc_obj_id) override;
- void AccessibilityScrollToMakeVisible(int acc_obj_id,
- const gfx::Rect& subfocus) override;
- void AccessibilityScrollToPoint(int acc_obj_id,
- const gfx::Point& point) override;
- void AccessibilitySetScrollOffset(int acc_obj_id,
- const gfx::Point& offset) override;
- void AccessibilitySetSelection(int anchor_object_id,
- int anchor_offset,
- int focus_object_id,
- int focus_offset) override;
- void AccessibilitySetValue(int acc_obj_id, const base::string16& value)
- override;
+ void AccessibilityPerformAction(const ui::AXActionData& data) override;
bool AccessibilityViewHasFocus() const override;
gfx::Rect AccessibilityGetViewBounds() const override;
gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const override;
- void AccessibilityHitTest(const gfx::Point& point) override;
- void AccessibilitySetAccessibilityFocus(int acc_obj_id) override;
void AccessibilityFatalError() override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
@@ -208,9 +194,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// SiteInstanceImpl::Observer
void RenderProcessGone(SiteInstanceImpl* site_instance) override;
- // shell::InterfaceFactory<media::mojom::ServiceFactory>
- void Create(const shell::Identity& remote_identity,
- media::mojom::ServiceFactoryRequest request) override;
+ // service_manager::InterfaceFactory<media::mojom::InterfaceFactory>
+ void Create(const service_manager::Identity& remote_identity,
+ media::mojom::InterfaceFactoryRequest request) override;
// Creates a RenderFrame in the renderer process.
bool CreateRenderFrame(int proxy_routing_id,
@@ -279,7 +265,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// distinguished by owning a RenderWidgetHost, which manages input events
// and painting for this frame and its contiguous local subtree in the
// renderer process.
- bool is_local_root() { return !!render_widget_host_; }
+ bool is_local_root() const { return !!render_widget_host_; }
// Returns the RenderWidgetHostImpl attached to this frame or the nearest
// ancestor frame, which could potentially be the root. For most input
@@ -295,6 +281,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
GlobalFrameRoutingId GetGlobalFrameRoutingId();
+#if defined(OS_ANDROID)
+ scoped_refptr<AppWebMessagePortMessageFilter>
+ GetAppWebMessagePortMessageFilter(int routing_id);
+#endif
+
// This function is called when this is a swapped out RenderFrameHost that
// lives in the same process as the parent frame. The
// |cross_process_frame_connector| allows the non-swapped-out
@@ -341,18 +332,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// RenderFrameHost that will issue the transferring request.
std::unique_ptr<NavigationHandleImpl> PassNavigationHandleOwnership();
- // Called on the pending RenderFrameHost when the network response is ready to
- // commit. We should ensure that the old RenderFrameHost runs its unload
- // handler and determine whether a transfer to a different RenderFrameHost is
- // needed.
- void OnCrossSiteResponse(const GlobalRequestID& global_request_id,
- std::unique_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request,
- const std::vector<GURL>& transfer_url_chain,
- const Referrer& referrer,
- ui::PageTransition page_transition,
- bool should_replace_current_entry);
-
// Tells the renderer that this RenderFrame is being swapped out for one in a
// different renderer process. It should run its unload handler and move to
// a blank document. If |proxy| is not null, it should also create a
@@ -395,15 +374,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Navigates to an interstitial page represented by the provided data URL.
void NavigateToInterstitialURL(const GURL& data_url);
- // Treat this prospective navigation as though it originated from the frame.
- // Used, e.g., for a navigation request that originated from a RemoteFrame.
- // |source_site_instance| is the SiteInstance of the frame that initiated the
- // navigation.
- // TODO(creis): Remove this method and have RenderFrameProxyHost call
- // RequestOpenURL with its FrameTreeNode.
- void OpenURL(const FrameHostMsg_OpenURL_Params& params,
- SiteInstance* source_site_instance);
-
// Stop the load in progress.
void Stop();
@@ -456,14 +426,14 @@ class CONTENT_EXPORT RenderFrameHostImpl
// cross-process window.focus() calls.
void SetFocusedFrame();
- // This is used to clear focus inside an inner WebContents when focus shifts
- // to a frame in the outer WebContents or a sibling WebContents.
- void ClearFocusedFrame();
-
// Deletes the current selection plus the specified number of characters
// before and after the selection or caret.
void ExtendSelectionAndDelete(size_t before, size_t after);
+ // Deletes text before and after the current cursor position, excluding the
+ // selection.
+ void DeleteSurroundingText(size_t before, size_t after);
+
// Notifies the RenderFrame that the JavaScript message that was shown was
// closed by the user.
void JavaScriptDialogClosed(IPC::Message* reply_msg,
@@ -595,12 +565,20 @@ class CONTENT_EXPORT RenderFrameHostImpl
// no longer on the stack when we attempt to swap it out.
void SuppressFurtherDialogs();
+ void SetHasReceivedUserGesture();
+
+ void ClearFocusedElement();
+
// PlzNavigate: returns the LoFi state of the last successful navigation that
// made a network request.
LoFiState last_navigation_lofi_state() const {
return last_navigation_lofi_state_;
}
+ bool has_focused_editable_element() const {
+ return has_focused_editable_element_;
+ }
+
protected:
friend class RenderFrameHostFactory;
@@ -616,7 +594,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- bool hidden);
+ bool hidden,
+ bool renderer_initiated_creation);
private:
friend class TestRenderFrameHost;
@@ -641,10 +620,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
LoadEventForwardingWhilePendingDeletion);
// IPC Message handlers.
- void OnAddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id);
+ void OnDidAddMessageToConsole(int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id);
void OnDetach();
void OnFrameFocused();
void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
@@ -691,7 +670,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnDidAddContentSecurityPolicy(const ContentSecurityPolicyHeader& header);
void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy);
void OnUpdateToUniqueOrigin(bool is_potentially_trustworthy_unique_origin);
- void OnDidAssignPageId(int32_t page_id);
void OnDidChangeSandboxFlags(int32_t frame_routing_id,
blink::WebSandboxFlags flags);
void OnDidChangeFrameOwnerProperties(int32_t frame_routing_id,
@@ -724,6 +702,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
bool success,
const std::set<std::string>& digests_of_uris_of_serialized_resources,
base::TimeDelta renderer_main_thread_time);
+ void OnSelectionChanged(const base::string16& text,
+ uint32_t offset,
+ const gfx::Range& range);
+ void OnFocusedNodeChanged(bool is_editable_element,
+ const gfx::Rect& bounds_in_frame_widget);
#if defined(USE_EXTERNAL_POPUP_MENU)
void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
@@ -806,10 +789,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Sends a navigate message to the RenderFrame and notifies DevTools about
// navigation happening. Should be used instead of sending the message
// directly.
- void SendNavigateMessage(
- const content::CommonNavigationParams& common_params,
- const content::StartNavigationParams& start_params,
- const content::RequestNavigationParams& request_params);
+ void SendNavigateMessage(const CommonNavigationParams& common_params,
+ const StartNavigationParams& start_params,
+ const RequestNavigationParams& request_params);
// Returns the child FrameTreeNode if |child_frame_routing_id| is an
// immediate child of this FrameTreeNode. |child_frame_routing_id| is
@@ -830,6 +812,14 @@ class CONTENT_EXPORT RenderFrameHostImpl
// happen before it fires (to avoid flakiness).
void DisableSwapOutTimerForTesting();
+ void OnRendererConnect(const service_manager::ServiceInfo& local_info,
+ const service_manager::ServiceInfo& remote_info);
+
+ // Returns ownership of the NavigationHandle associated with a navigation that
+ // just committed.
+ std::unique_ptr<NavigationHandleImpl> TakeNavigationHandleForCommit(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
+
// 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
@@ -970,8 +960,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// SiteInstance. May be null in tests.
std::unique_ptr<TimeoutMonitor> swapout_event_monitor_timeout_;
- std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
- std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
+ std::unique_ptr<service_manager::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
+
+ service_manager::ServiceInfo browser_info_;
+ service_manager::ServiceInfo renderer_info_;
+
+ int on_connect_handler_id_ = 0;
+
+#if defined(OS_ANDROID)
+ // The filter for MessagePort messages between an Android apps and web.
+ scoped_refptr<AppWebMessagePortMessageFilter>
+ app_web_message_port_message_filter_;
+#endif
std::unique_ptr<WebBluetoothServiceImpl> web_bluetooth_service_;
@@ -1040,6 +1041,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// called (no pending instance should be set).
bool should_reuse_web_ui_;
+ // If true, then the RenderFrame has selected text.
+ bool has_selection_;
+
// PlzNavigate: The LoFi state of the last navigation. This is used during
// history navigation of subframes to ensure that subframes navigate with the
// same LoFi status as the top-level frame.
@@ -1048,15 +1052,27 @@ class CONTENT_EXPORT RenderFrameHostImpl
mojo::Binding<mojom::FrameHost> frame_host_binding_;
mojom::FramePtr frame_;
+ // If this is true then this object was created in response to a renderer
+ // initiated request. Init() will be called, and until then navigation
+ // requests should be queued.
+ bool waiting_for_init_;
+
+ // If true then this frame's document has a focused element which is editable.
+ bool has_focused_editable_element_;
+
+ typedef std::pair<CommonNavigationParams, BeginNavigationParams>
+ PendingNavigation;
+ std::unique_ptr<PendingNavigation> pendinging_navigate_;
+
// Callback for responding when
// |FrameHostMsg_TextSurroundingSelectionResponse| message comes.
TextSurroundingSelectionCallback text_surrounding_selection_callback_;
- std::vector<std::unique_ptr<shell::InterfaceRegistry>> media_registries_;
+ std::vector<std::unique_ptr<service_manager::InterfaceRegistry>>
+ media_registries_;
std::unique_ptr<AssociatedInterfaceProviderImpl>
remote_associated_interfaces_;
-
// NOTE: This must be the last member.
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
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 712cb23f2da..380f6871749 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -7,7 +7,9 @@
#include <stddef.h>
#include <algorithm>
+#include <string>
#include <utility>
+#include <vector>
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
@@ -18,7 +20,6 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_navigation_entry.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
@@ -86,7 +87,8 @@ RenderFrameHostManager::~RenderFrameHostManager() {
void RenderFrameHostManager::Init(SiteInstance* site_instance,
int32_t view_routing_id,
int32_t frame_routing_id,
- int32_t widget_routing_id) {
+ int32_t widget_routing_id,
+ bool renderer_initiated_creation) {
DCHECK(site_instance);
// TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must
// hold true to avoid having two RenderWidgetHosts for the top-level frame.
@@ -95,7 +97,8 @@ void RenderFrameHostManager::Init(SiteInstance* site_instance,
view_routing_id == widget_routing_id);
SetRenderFrameHost(CreateRenderFrameHost(site_instance, view_routing_id,
frame_routing_id, widget_routing_id,
- delegate_->IsHidden()));
+ delegate_->IsHidden(),
+ renderer_initiated_creation));
// Notify the delegate of the creation of the current RenderFrameHost.
// Do this only for subframes, as the main frame case is taken care of by
@@ -231,7 +234,8 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
// with the new render frame if necessary. Note that this call needs to
// occur before initializing the RenderView; the flow of creating the
// RenderView can cause browser-side code to execute that expects the this
- // RFH's shell::InterfaceRegistry to be initialized (e.g., if the site is a
+ // RFH's service_manager::InterfaceRegistry to be initialized (e.g., if the
+ // site is a
// WebUI site that is handled via Mojo, then Mojo WebUI code in //chrome
// will add an interface to this RFH's InterfaceRegistry).
dest_render_frame_host->SetUpMojoIfNeeded();
@@ -240,10 +244,10 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
return nullptr;
if (GetNavigatingWebUI()) {
- // A new RenderView was created and there is a navigating WebUI which
- // never interacted with it. So notify the WebUI using RenderViewCreated.
- GetNavigatingWebUI()->RenderViewCreated(
- dest_render_frame_host->render_view_host());
+ // A new RenderFrame was created and there is a navigating WebUI which
+ // never interacted with it. So notify the WebUI using
+ // RenderFrameCreated.
+ GetNavigatingWebUI()->RenderFrameCreated(dest_render_frame_host);
}
// Now that we've created a new renderer, be sure to hide it if it isn't
@@ -280,26 +284,18 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
// If entry includes the request ID of a request that is being transferred,
// the destination render frame will take ownership, so release ownership of
- // the request.
- if (cross_site_transferring_request_.get() &&
- cross_site_transferring_request_->request_id() ==
+ // the transferring NavigationHandle.
+ if (transfer_navigation_handle_.get() &&
+ transfer_navigation_handle_->GetGlobalRequestID() ==
entry.transferred_global_request_id()) {
- cross_site_transferring_request_->ReleaseRequest();
-
- DCHECK(transfer_navigation_handle_);
-
- // Update the pending NavigationEntry ID on the transferring handle.
- // TODO(creis): Make this line unnecessary by avoiding having a pending
- // entry for transfer navigations. See https://crbug.com/495161.
- transfer_navigation_handle_->update_entry_id_for_transfer(
- entry.GetUniqueID());
-
// The navigating RenderFrameHost should take ownership of the
// NavigationHandle that came from the transferring RenderFrameHost.
dest_render_frame_host->SetNavigationHandle(
std::move(transfer_navigation_handle_));
+
+ dest_render_frame_host->navigation_handle()->set_render_frame_host(
+ dest_render_frame_host);
}
- DCHECK(!transfer_navigation_handle_);
return dest_render_frame_host;
}
@@ -421,17 +417,10 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
void RenderFrameHostManager::OnCrossSiteResponse(
RenderFrameHostImpl* transferring_render_frame_host,
const GlobalRequestID& global_request_id,
- std::unique_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
bool should_replace_current_entry) {
- // We should only get here for transfer navigations. Most cross-process
- // navigations can just continue and wait to run the unload handler (by
- // swapping out) when the new navigation commits.
- CHECK(cross_site_transferring_request);
-
// A transfer should only have come from our pending or current RFH. If it
// started as a cross-process navigation via OpenURL, this is the pending
// one. If it wasn't cross-process until the transfer, this is the current
@@ -458,16 +447,7 @@ void RenderFrameHostManager::OnCrossSiteResponse(
// after it started navigating.
transfer_navigation_handle_ =
transferring_render_frame_host->PassNavigationHandleOwnership();
-
- // If something caused the cancellation of this navigation on the UI thread
- // (possibly for security reasons) the navigation should not be allowed to
- // proceed.
- if (!transfer_navigation_handle_)
- return;
-
- // Store the transferring request so that we can release it if the transfer
- // navigation matches.
- cross_site_transferring_request_ = std::move(cross_site_transferring_request);
+ CHECK(transfer_navigation_handle_);
// Set the transferring RenderFrameHost as not loading, so that it does not
// emit a DidStopLoading notification if it is destroyed when creating the
@@ -481,6 +461,14 @@ void RenderFrameHostManager::OnCrossSiteResponse(
std::vector<GURL> rest_of_chain = transfer_url_chain;
rest_of_chain.pop_back();
+ // |extra_headers| passed to RequestTransferURL below are always empty for
+ // now, because there are no known scenarios where headers (from POST request
+ // made from one renderer) need to be forwarded into the renderer where that
+ // request ends up being transfered to. In particular, XSSAuditor doesn't
+ // look at the headers (e.g. the Content-Type header) when analyzing the body
+ // of the POST request.
+ std::string extra_headers;
+
transferring_render_frame_host->frame_tree_node()
->navigator()
->RequestTransferURL(
@@ -488,15 +476,16 @@ void RenderFrameHostManager::OnCrossSiteResponse(
referrer, page_transition, global_request_id,
should_replace_current_entry,
transfer_navigation_handle_->IsPost() ? "POST" : "GET",
- transfer_navigation_handle_->resource_request_body());
-
- // The transferring request was only needed during the RequestTransferURL
- // call, so it is safe to clear at this point.
- cross_site_transferring_request_.reset();
+ transfer_navigation_handle_->resource_request_body(), extra_headers);
// If the navigation continued, the NavigationHandle should have been
// transfered to a RenderFrameHost. In the other cases, it should be cleared.
- transfer_navigation_handle_.reset();
+ // If the NavigationHandle wasn't claimed, this will lead to the cancelation
+ // of the request in the network stack.
+ if (transfer_navigation_handle_) {
+ transfer_navigation_handle_->set_is_transferring(false);
+ transfer_navigation_handle_.reset();
+ }
// If the navigation in the new renderer did not start, inform the
// FrameTreeNode that it stopped loading.
@@ -659,6 +648,10 @@ void RenderFrameHostManager::SwapOutOldFrame(
CreateRenderFrameProxyHost(old_render_frame_host->GetSiteInstance(),
old_render_frame_host->render_view_host());
+ // Reset any NavigationHandle in the RenderFrameHost. This will prevent any
+ // ongoing navigation from attempting to transfer.
+ old_render_frame_host->SetNavigationHandle(nullptr);
+
// Tell the old RenderFrameHost to swap out and be replaced by the proxy.
old_render_frame_host->SwapOut(proxy, true);
@@ -676,11 +669,12 @@ void RenderFrameHostManager::DiscardUnusedFrame(
// TODO(carlosk): this code is very similar to what can be found in
// SwapOutOldFrame and we should see that these are unified at some point.
- // If the SiteInstance for the pending RFH is being used by others don't
- // delete the RFH. Just swap it out and it can be reused at a later point.
- // In --site-per-process, RenderFrameHosts are not kept around and are
- // deleted when not used, replaced by RenderFrameProxyHosts.
+ // If the SiteInstance for the pending RFH is being used by others, ensure
+ // that it is replaced by a RenderFrameProxyHost to allow other frames to
+ // communicate to this frame.
SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
+ RenderViewHostImpl* rvh = render_frame_host->render_view_host();
+ RenderFrameProxyHost* proxy = nullptr;
if (site_instance->HasSite() && site_instance->active_frame_count() > 1) {
// Any currently suspended navigations are no longer needed.
render_frame_host->CancelSuspendedNavigations();
@@ -690,14 +684,30 @@ void RenderFrameHostManager::DiscardUnusedFrame(
// |render_frame_host|, as this method is only called to discard a pending
// or speculative RenderFrameHost, i.e. one that has never hosted an actual
// document.
- RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
- if (!proxy) {
- proxy = CreateRenderFrameProxyHost(site_instance,
- render_frame_host->render_view_host());
- }
+ proxy = GetRenderFrameProxyHost(site_instance);
+ if (!proxy)
+ proxy = CreateRenderFrameProxyHost(site_instance, rvh);
+ }
+
+ // Doing this is important in the case where the replacement proxy is created
+ // above, as the RenderViewHost will continue to exist and should be
+ // considered swapped out if it is ever reused. When there's no replacement
+ // proxy, this doesn't really matter, as the RenderViewHost will be destroyed
+ // shortly, since |render_frame_host| is its last active frame and will be
+ // deleted below. See https://crbug.com/627400.
+ if (frame_tree_node_->IsMainFrame()) {
+ rvh->set_main_frame_routing_id(MSG_ROUTING_NONE);
+ rvh->set_is_active(false);
+ rvh->set_is_swapped_out(true);
}
render_frame_host.reset();
+
+ // If a new RenderFrameProxyHost was created above, or if the old proxy isn't
+ // live, create the RenderFrameProxy in the renderer, so that other frames
+ // can still communicate with this frame. See https://crbug.com/653746.
+ if (proxy && !proxy->is_render_frame_proxy_live())
+ proxy->InitRenderFrameProxy();
}
bool RenderFrameHostManager::DeleteFromPendingList(
@@ -767,7 +777,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// The appropriate RenderFrameHost to commit the navigation.
RenderFrameHostImpl* navigation_rfh = nullptr;
- bool notify_webui_of_rv_creation = false;
+ bool notify_webui_of_rf_creation = false;
// Reuse the current RenderFrameHost if its SiteInstance matches the
// navigation's.
@@ -837,7 +847,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
request.common_params().url, request.bindings());
speculative_render_frame_host_->CommitPendingWebUI();
DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui());
- notify_webui_of_rv_creation =
+ notify_webui_of_rf_creation =
changed_web_ui && speculative_render_frame_host_->web_ui();
navigation_rfh = speculative_render_frame_host_.get();
@@ -851,13 +861,13 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// RFH isn't live.)
CommitPending();
- // Notify the WebUI of the creation of the RenderView if needed (the
- // newly created WebUI has just been committed by CommitPending, so
+ // Notify the WebUI about the new RenderFrame if needed (the newly
+ // created WebUI has just been committed by CommitPending, so
// GetNavigatingWebUI() below will return false).
- if (notify_webui_of_rv_creation && render_frame_host_->web_ui()) {
- render_frame_host_->web_ui()->RenderViewCreated(
- render_frame_host_->render_view_host());
- notify_webui_of_rv_creation = false;
+ if (notify_webui_of_rf_creation && render_frame_host_->web_ui()) {
+ render_frame_host_->web_ui()->RenderFrameCreated(
+ render_frame_host_.get());
+ notify_webui_of_rf_creation = false;
}
}
}
@@ -871,7 +881,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
if (!ReinitializeRenderFrame(navigation_rfh))
return nullptr;
- notify_webui_of_rv_creation = true;
+ notify_webui_of_rf_creation = true;
if (navigation_rfh == render_frame_host_.get()) {
// TODO(nasko): This is a very ugly hack. The Chrome extensions process
@@ -885,11 +895,11 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
}
}
- // If a WebUI was created in a speculative RenderFrameHost or a new RenderView
- // was created then the WebUI never interacted with the RenderView. Notify
- // using RenderViewCreated.
- if (notify_webui_of_rv_creation && GetNavigatingWebUI())
- GetNavigatingWebUI()->RenderViewCreated(navigation_rfh->render_view_host());
+ // If a WebUI was created in a speculative RenderFrameHost or a new
+ // RenderFrame was created then the WebUI never interacted with the
+ // RenderFrame or its RenderView. Notify using RenderFrameCreated.
+ if (notify_webui_of_rf_creation && GetNavigatingWebUI())
+ GetNavigatingWebUI()->RenderFrameCreated(navigation_rfh);
return navigation_rfh;
}
@@ -1236,8 +1246,8 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
ConvertToSiteInstance(new_instance_descriptor, candidate_instance);
// If |force_swap| is true, we must use a different SiteInstance than the
// current one. If we didn't, we would have two RenderFrameHosts in the same
- // SiteInstance and the same frame, resulting in page_id conflicts for their
- // NavigationEntries.
+ // SiteInstance and the same frame, breaking lookup of RenderFrameHosts by
+ // SiteInstance.
if (force_swap)
CHECK_NE(new_instance, current_instance);
@@ -1431,6 +1441,13 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
!SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
dest_url)) {
+ if (GetContentClient()
+ ->browser()
+ ->ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
+ dest_url, current_instance)) {
+ return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance());
+ }
+
// This is a cross-site subframe of a non-isolated origin, so place this
// frame in the default subframe site instance.
return SiteInstanceDescriptor(
@@ -1484,7 +1501,7 @@ bool RenderFrameHostManager::IsRendererTransferNeededForNavigation(
if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
(!frame_tree_node_->IsMainFrame() ||
- rfh->GetSiteInstance()->is_default_subframe_site_instance())) {
+ rfh->GetSiteInstance()->IsDefaultSubframeSiteInstance())) {
// Always attempt a transfer in these cases.
return true;
}
@@ -1638,11 +1655,13 @@ void RenderFrameHostManager::CreateProxiesForNewNamedFrame() {
}
std::unique_ptr<RenderFrameHostImpl>
-RenderFrameHostManager::CreateRenderFrameHost(SiteInstance* site_instance,
- int32_t view_routing_id,
- int32_t frame_routing_id,
- int32_t widget_routing_id,
- bool hidden) {
+RenderFrameHostManager::CreateRenderFrameHost(
+ SiteInstance* site_instance,
+ int32_t view_routing_id,
+ int32_t frame_routing_id,
+ int32_t widget_routing_id,
+ bool hidden,
+ bool renderer_initiated_creation) {
if (frame_routing_id == MSG_ROUTING_NONE)
frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
@@ -1674,7 +1693,7 @@ RenderFrameHostManager::CreateRenderFrameHost(SiteInstance* site_instance,
return RenderFrameHostFactory::Create(
site_instance, render_view_host, render_frame_delegate_,
render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
- widget_routing_id, hidden);
+ widget_routing_id, hidden, renderer_initiated_creation);
}
// PlzNavigate
@@ -1729,7 +1748,8 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
}
new_render_frame_host = CreateRenderFrameHost(
- instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden);
+ instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden,
+ false);
RenderViewHostImpl* render_view_host =
new_render_frame_host->render_view_host();
@@ -2262,6 +2282,20 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
dest_url, source_instance, dest_instance, nullptr, transition,
dest_is_restore, dest_is_view_source_mode);
+ // Inform the transferring NavigationHandle of a transfer to a different
+ // SiteInstance. It is important do so now, in order to mark the request as
+ // transferring on the IO thread before attempting to destroy the pending RFH.
+ // This ensures the network request will not be destroyed along the pending
+ // RFH but will persist until it is picked up by the new RFH.
+ if (transfer_navigation_handle_.get() &&
+ transfer_navigation_handle_->GetGlobalRequestID() ==
+ transferred_request_id &&
+ new_instance.get() !=
+ transfer_navigation_handle_->GetRenderFrameHost()
+ ->GetSiteInstance()) {
+ transfer_navigation_handle_->Transfer();
+ }
+
// If we are currently navigating cross-process to a pending RFH for a
// different SiteInstance, we want to get back to normal and then navigate as
// usual. We will reuse the pending RFH below if it matches the destination
@@ -2298,11 +2332,11 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui());
// If a WebUI exists in the pending RenderFrameHost it was just created, as
- // well as the RenderView, and they never interacted. So notify it using
- // RenderViewCreated.
+ // well as the RenderFrame, and they never interacted. So notify the WebUI
+ // using RenderFrameCreated.
if (pending_render_frame_host_->web_ui()) {
- pending_render_frame_host_->web_ui()->RenderViewCreated(
- pending_render_frame_host_->render_view_host());
+ pending_render_frame_host_->web_ui()->RenderFrameCreated(
+ pending_render_frame_host_.get());
}
// Check if our current RFH is live before we set up a transition.
@@ -2321,8 +2355,9 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
if (is_transfer) {
// We don't need to stop the old renderer or run beforeunload/unload
// handlers, because those have already been done.
- DCHECK(cross_site_transferring_request_->request_id() ==
- transferred_request_id);
+ DCHECK(transfer_navigation_handle_ &&
+ transfer_navigation_handle_->GetGlobalRequestID() ==
+ transferred_request_id);
} else if (!pending_render_frame_host_->are_navigations_suspended()) {
// If the pending RFH hasn't already been suspended from a previous
// attempt to navigate it, then we need to wait for the beforeunload
@@ -2377,20 +2412,20 @@ void RenderFrameHostManager::UpdatePendingWebUIOnCurrentFrameHost(
render_frame_host_->IsRenderFrameLive()) {
// If a pending WebUI exists in the current RenderFrameHost and it has been
// updated and the associated RenderFrame is alive, notify the WebUI about
- // the RenderView.
- // Note: If the RenderFrame is not alive at this point the notification will
- // happen later, when the RenderView is created.
+ // the RenderFrame.
+ // Note: If the RenderFrame is not alive at this point the notification
+ // will happen later, when the RenderFrame is created.
if (render_frame_host_->pending_web_ui() == render_frame_host_->web_ui()) {
// If the active WebUI is being reused it has already interacting with
- // this RenderView in the past, so call RenderViewReused.
- render_frame_host_->pending_web_ui()->RenderViewReused(
- render_frame_host_->render_view_host(),
- frame_tree_node_->IsMainFrame());
+ // this RenderFrame and its RenderView in the past, so call
+ // RenderFrameReused.
+ render_frame_host_->pending_web_ui()->RenderFrameReused(
+ render_frame_host_.get());
} else {
// If this is a new WebUI it has never interacted with the existing
- // RenderView so call RenderViewCreated.
- render_frame_host_->pending_web_ui()->RenderViewCreated(
- render_frame_host_->render_view_host());
+ // RenderFrame so call RenderFrameCreated.
+ render_frame_host_->pending_web_ui()->RenderFrameCreated(
+ render_frame_host_.get());
}
}
}
@@ -2448,7 +2483,7 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
}
RenderViewHostImpl* RenderFrameHostManager::GetSwappedOutRenderViewHost(
- SiteInstance* instance) const {
+ SiteInstance* instance) const {
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
if (proxy)
return proxy->GetRenderViewHost();
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.h b/chromium/content/browser/frame_host/render_frame_host_manager.h
index 4533fb759d9..6ffb6f0671d 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -27,8 +27,6 @@
namespace content {
class BrowserContext;
-class CrossProcessFrameConnector;
-class CrossSiteTransferringRequest;
class FrameNavigationEntry;
class FrameTreeNode;
class InterstitialPageImpl;
@@ -47,7 +45,6 @@ class RenderWidgetHostDelegate;
class RenderWidgetHostView;
class TestWebContents;
class WebUIImpl;
-struct CommonNavigationParams;
struct ContentSecurityPolicyHeader;
struct FrameOwnerProperties;
struct FrameReplicationState;
@@ -198,7 +195,8 @@ class CONTENT_EXPORT RenderFrameHostManager
void Init(SiteInstance* site_instance,
int32_t view_routing_id,
int32_t frame_routing_id,
- int32_t widget_routing_id);
+ int32_t widget_routing_id,
+ bool renderer_initiated_creation);
// Returns the currently active RenderFrameHost.
//
@@ -299,12 +297,8 @@ class CONTENT_EXPORT RenderFrameHostManager
// The |pending_render_frame_host| is ready to commit a page. We should
// ensure that the old RenderFrameHost runs its unload handler first and
// determine whether a RenderFrameHost transfer is needed.
- // |cross_site_transferring_request| is NULL if a request is not being
- // transferred between renderers.
void OnCrossSiteResponse(RenderFrameHostImpl* pending_render_frame_host,
const GlobalRequestID& global_request_id,
- std::unique_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
@@ -676,7 +670,8 @@ class CONTENT_EXPORT RenderFrameHostManager
int32_t view_routing_id,
int32_t frame_routing_id,
int32_t widget_routing_id,
- bool hidden);
+ bool hidden,
+ bool renderer_initiated_creation);
// PlzNavigate
// Create and initialize a speculative RenderFrameHost for an ongoing
@@ -777,12 +772,6 @@ class CONTENT_EXPORT RenderFrameHostManager
// Note: This member is not used in PlzNavigate.
std::unique_ptr<RenderFrameHostImpl> pending_render_frame_host_;
- // If a pending request needs to be transferred to another process, this
- // owns the request until it's transferred to the new process, so it will be
- // cleaned up if the navigation is cancelled. Otherwise, this is NULL.
- std::unique_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request_;
-
// This is used to temporarily store the NavigationHandle during
// transferring navigations. The handle needs to be stored because the old
// RenderFrameHost may be discarded before a new RenderFrameHost is created
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 b57c95210c6..d89d5557b45 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
@@ -45,11 +45,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_frame_navigation_observer.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/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/request_handler_util.h"
@@ -159,8 +159,8 @@ class RenderFrameHostManagerTest : public ContentBrowserTest {
void StartEmbeddedServer() {
// Support multiple sites on the embedded test server.
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
// Returns a URL on foo.com with the given path.
@@ -2079,7 +2079,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
NavigationControllerImpl::CreateNavigationEntry(
url1, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), shell()->web_contents()->GetBrowserContext()));
- cloned_entry->SetPageID(0);
prev_entry = shell()->web_contents()->GetController().GetEntryAtIndex(0);
cloned_entry->SetPageState(prev_entry->GetPageState());
const std::vector<base::FilePath>& cloned_files =
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 09eacd99209..f33bea5eb2f 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
@@ -17,7 +17,6 @@
#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_request.h"
@@ -343,15 +342,11 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
: old_rfh;
EXPECT_TRUE(old_rfh->is_active());
- // Commit the navigation with a new page ID.
- int32_t max_page_id =
- contents()->GetMaxPageIDForSiteInstance(active_rfh->GetSiteInstance());
-
// Use an observer to avoid accessing a deleted renderer later on when the
// state is being checked.
RenderFrameDeletedObserver rfh_observer(old_rfh);
RenderViewHostDeletedObserver rvh_observer(old_rfh->GetRenderViewHost());
- active_rfh->SendNavigate(max_page_id + 1, entry_id, true, url);
+ active_rfh->SendNavigate(entry_id, true, url);
// Make sure that we start to run the unload handler at the time of commit.
if (old_rfh != active_rfh && !rfh_observer.deleted()) {
@@ -416,7 +411,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
// BeforeUnload finishes.
ntp_rfh->SendBeforeUnloadACK(true);
- dest_rfh->SendNavigate(101, entry_id, true, kDestUrl);
+ dest_rfh->SendNavigate(entry_id, true, kDestUrl);
ntp_rfh->OnSwappedOut();
}
@@ -526,7 +521,7 @@ TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
contents2->GetMainFrame()->PrepareForCommit();
TestRenderFrameHost* ntp_rfh2 = contents2->GetMainFrame();
EXPECT_FALSE(contents2->CrossProcessNavigationPending());
- ntp_rfh2->SendNavigate(100, entry_id, true, kChromeUrl);
+ ntp_rfh2->SendNavigate(entry_id, true, kChromeUrl);
// The second one is the opposite, creating a cross-site transition and
// requiring a beforeunload ack.
@@ -538,7 +533,7 @@ TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
TestRenderFrameHost* dest_rfh2 = contents2->GetPendingMainFrame();
ASSERT_TRUE(dest_rfh2);
- dest_rfh2->SendNavigate(101, entry_id, true, kDestUrl);
+ dest_rfh2->SendNavigate(entry_id, true, kDestUrl);
// The two RFH's should be different in every way.
EXPECT_NE(contents()->GetMainFrame()->GetProcess(), dest_rfh2->GetProcess());
@@ -556,8 +551,7 @@ TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
kChromeUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
contents2->GetMainFrame()->PrepareForCommit();
- contents2->GetPendingMainFrame()->SendNavigate(102, entry_id, true,
- kChromeUrl);
+ contents2->GetPendingMainFrame()->SendNavigate(entry_id, true, kChromeUrl);
EXPECT_NE(contents()->GetMainFrame()->GetSiteInstance(),
contents2->GetMainFrame()->GetSiteInstance());
@@ -651,7 +645,7 @@ TEST_F(RenderFrameHostManagerTest, UpdateFaviconURLWhilePendingSwapOut) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
- contents()->TestDidNavigate(rfh2, 1, entry_id, true, kDestUrl,
+ contents()->TestDidNavigate(rfh2, entry_id, true, kDestUrl,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(rfh1->is_active());
EXPECT_TRUE(rfh2->is_active());
@@ -849,9 +843,7 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
ASSERT_TRUE(contents()->GetPendingMainFrame())
<< "Expected new pending RenderFrameHost to be created.";
RenderFrameHost* last_rfh = contents()->GetPendingMainFrame();
- int32_t new_id =
- contents()->GetMaxPageIDForSiteInstance(last_rfh->GetSiteInstance()) + 1;
- contents()->GetPendingMainFrame()->SendNavigate(new_id, entry_id, true, kUrl);
+ contents()->GetPendingMainFrame()->SendNavigate(entry_id, true, kUrl);
EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
NavigationEntry* last_committed = controller().GetLastCommittedEntry();
@@ -878,7 +870,7 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
// The renderer sends a commit.
contents()->GetMainFrame()->SendNavigateWithTransition(
- new_id, entry_id, false, kUrl, ui::PAGE_TRANSITION_TYPED);
+ entry_id, false, kUrl, ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
EXPECT_FALSE(controller().GetPendingEntry());
@@ -923,7 +915,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
- NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
+ NULL /* instance */, kUrl1, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = NavigateToEntry(manager, entry1);
@@ -943,7 +935,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// 2) Navigate to next site. -------------------------
const GURL kUrl2("http://www.google.com/foo");
NavigationEntryImpl entry2(
- NULL /* instance */, -1 /* page_id */, kUrl2,
+ NULL /* instance */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
@@ -962,7 +954,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// 3) Cross-site navigate to next site. --------------
const GURL kUrl3("http://webkit.org/");
NavigationEntryImpl entry3(
- NULL /* instance */, -1 /* page_id */, kUrl3,
+ NULL /* instance */, kUrl3,
Referrer(kUrl2, blink::WebReferrerPolicyDefault),
base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
false /* is_renderer_init */);
@@ -1002,7 +994,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
EXPECT_TRUE(initial_rfh);
const GURL kUrl("chrome://foo");
- NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(NULL /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -1058,14 +1050,14 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
RenderFrameHostManager* manager1 =
web_contents1->GetRenderManagerForTesting();
// Test the case that new RVH is considered live.
- manager1->current_host()->CreateRenderView(-1, MSG_ROUTING_NONE, -1,
+ manager1->current_host()->CreateRenderView(-1, MSG_ROUTING_NONE,
FrameReplicationState(), false);
EXPECT_TRUE(manager1->current_host()->IsRenderViewLive());
EXPECT_TRUE(manager1->current_frame_host()->IsRenderFrameLive());
// Navigate to a WebUI page.
const GURL kUrl1("chrome://foo");
- NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
+ NavigationEntryImpl entry1(NULL /* instance */, kUrl1,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -1092,12 +1084,12 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
web_contents2->GetRenderManagerForTesting();
// Make sure the new RVH is considered live. This is usually done in
// RenderWidgetHost::Init when opening a new tab from a link.
- manager2->current_host()->CreateRenderView(-1, MSG_ROUTING_NONE, -1,
+ manager2->current_host()->CreateRenderView(-1, MSG_ROUTING_NONE,
FrameReplicationState(), false);
EXPECT_TRUE(manager2->current_host()->IsRenderViewLive());
const GURL kUrl2("chrome://foo/bar");
- NavigationEntryImpl entry2(NULL /* instance */, -1 /* page_id */, kUrl2,
+ NavigationEntryImpl entry2(NULL /* instance */, kUrl2,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
@@ -1189,7 +1181,6 @@ TEST_F(RenderFrameHostManagerTest, PageDoesBackAndReload) {
// Before that RFH has committed, the evil page reloads itself.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.url = kUrl2;
@@ -1274,7 +1265,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
// The back navigation commits.
const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- entry1->GetPageID(), entry1->GetUniqueID(), false, entry1->GetURL());
+ entry1->GetUniqueID(), false, entry1->GetURL());
EXPECT_TRUE(rfh2->IsWaitingForUnloadACK());
EXPECT_FALSE(rfh2->is_active());
@@ -1283,7 +1274,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
contents()->GetMainFrame()->PrepareForCommit();
const NavigationEntry* entry2 = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- entry2->GetPageID(), entry2->GetUniqueID(), false, entry2->GetURL());
+ entry2->GetUniqueID(), false, entry2->GetURL());
EXPECT_TRUE(main_test_rfh()->is_active());
}
@@ -1449,7 +1440,7 @@ TEST_F(RenderFrameHostManagerTest, DisownOpenerDuringNavigation) {
// The back navigation commits.
const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- entry1->GetPageID(), entry1->GetUniqueID(), false, entry1->GetURL());
+ entry1->GetUniqueID(), false, entry1->GetURL());
// Ensure the opener is still cleared.
EXPECT_FALSE(contents()->HasOpener());
@@ -1483,7 +1474,7 @@ TEST_F(RenderFrameHostManagerTest, DisownOpenerAfterNavigation) {
contents()->GetMainFrame()->PrepareForCommit();
const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- entry1->GetPageID(), entry1->GetUniqueID(), false, entry1->GetURL());
+ entry1->GetUniqueID(), false, entry1->GetURL());
// Disown the opener from rfh2.
rfh2->DidChangeOpener(MSG_ROUTING_NONE);
@@ -1509,7 +1500,7 @@ TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
// Make sure the new opener RVH is considered live.
opener1_manager->current_host()->CreateRenderView(
- -1, MSG_ROUTING_NONE, -1, FrameReplicationState(), false);
+ -1, MSG_ROUTING_NONE, FrameReplicationState(), false);
EXPECT_TRUE(opener1_manager->current_host()->IsRenderViewLive());
EXPECT_TRUE(opener1_manager->current_frame_host()->IsRenderFrameLive());
@@ -1609,7 +1600,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
- NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
+ NULL /* instance */, kUrl1, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = NavigateToEntry(manager, entry1);
@@ -1630,7 +1621,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
// Guests stay in the same process on navigation.
const GURL kUrl2("http://www.chromium.org");
NavigationEntryImpl entry2(
- NULL /* instance */, -1 /* page_id */, kUrl2,
+ NULL /* instance */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
@@ -1665,7 +1656,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
- NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
+ NavigationEntryImpl entry1(NULL /* instance */, kUrl1,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -1689,7 +1680,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
// 2) Cross-site navigate to next site. -------------------------
const GURL kUrl2("http://www.example.com");
NavigationEntryImpl entry2(
- NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(),
+ NULL /* instance */, kUrl2, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry2);
@@ -1738,7 +1729,7 @@ TEST_F(RenderFrameHostManagerTest, CloseWithPendingWhileUnresponsive) {
// Simulate the unresponsiveness timer. The tab should close.
contents()->RendererUnresponsive(
rfh1->render_view_host()->GetWidget(),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
EXPECT_TRUE(close_delegate.is_closed());
}
@@ -1771,7 +1762,7 @@ TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
EXPECT_TRUE(rfh1->is_active());
// The new page commits.
- contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2,
+ contents()->TestDidNavigate(rfh2, entry_id, true, kUrl2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
@@ -1813,7 +1804,7 @@ TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
- contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2,
+ contents()->TestDidNavigate(rfh2, entry_id, true, kUrl2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
@@ -1857,7 +1848,7 @@ TEST_F(RenderFrameHostManagerTest,
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
- contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2,
+ contents()->TestDidNavigate(rfh2, entry_id, true, kUrl2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
@@ -1962,7 +1953,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
contents()->GetFrameTree()->root()->child_at(1)->render_manager();
// 1) The first navigation.
- NavigationEntryImpl entryA(NULL /* instance */, -1 /* page_id */, kUrlA,
+ NavigationEntryImpl entryA(NULL /* instance */, kUrlA,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -1980,7 +1971,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
EXPECT_TRUE(host1->GetSiteInstance()->HasSite());
// 2) Cross-site navigate both frames to next site.
- NavigationEntryImpl entryB(NULL /* instance */, -1 /* page_id */, kUrlB,
+ NavigationEntryImpl entryB(NULL /* instance */, kUrlB,
Referrer(kUrlA, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2091,7 +2082,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
blink::WebSandboxFlags::None, FrameOwnerProperties());
RenderFrameHostManager* iframe =
contents()->GetFrameTree()->root()->child_at(0)->render_manager();
- NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl2,
+ NavigationEntryImpl entry(NULL /* instance */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2145,7 +2136,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// pending RVH has bindings.
const GURL kWebUIUrl("chrome://foo");
NavigationEntryImpl webui_entry(
- nullptr /* instance */, -1 /* page_id */, kWebUIUrl, Referrer(),
+ nullptr /* instance */, kWebUIUrl, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostManager* main_rfhm = contents()->GetRenderManagerForTesting();
@@ -2158,7 +2149,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// should not grant WebUI bindings to the subframe's RVH.
const GURL kSubframeUrl("http://bar.com");
NavigationEntryImpl subframe_entry(
- nullptr /* instance */, -1 /* page_id */, kSubframeUrl, Referrer(),
+ nullptr /* instance */, kSubframeUrl, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
false /* is_renderer_init */);
RenderFrameHostImpl* bar_rfh = NavigateToEntry(subframe_rfhm, subframe_entry);
@@ -2393,7 +2384,7 @@ TEST_F(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
RenderFrameHostManager* child3 = root->child_at(2)->render_manager();
// Navigate first two subframes to B.
- NavigationEntryImpl entryB(nullptr /* instance */, -1 /* page_id */, kUrlB,
+ NavigationEntryImpl entryB(nullptr /* instance */, kUrlB,
Referrer(kUrlA, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2406,7 +2397,7 @@ TEST_F(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
child2->DidNavigateFrame(host2, true);
// Navigate the third subframe to C.
- NavigationEntryImpl entryC(nullptr /* instance */, -1 /* page_id */, kUrlC,
+ NavigationEntryImpl entryC(nullptr /* instance */, kUrlC,
Referrer(kUrlA, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2481,7 +2472,7 @@ TEST_F(RenderFrameHostManagerTest,
RenderFrameHostManager* child = root->child_at(0)->render_manager();
// Navigate subframe to B.
- NavigationEntryImpl entryB(nullptr /* instance */, -1 /* page_id */, kUrlB,
+ NavigationEntryImpl entryB(nullptr /* instance */, kUrlB,
Referrer(kUrlA, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2495,7 +2486,7 @@ TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(main_test_rfh()->GetView()->HasFocus());
// Navigate the subframe to C.
- NavigationEntryImpl entryC(nullptr /* instance */, -1 /* page_id */, kUrlC,
+ NavigationEntryImpl entryC(nullptr /* instance */, kUrlC,
Referrer(kUrlA, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -2534,7 +2525,6 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
NavigationControllerImpl::CreateNavigationEntry(
kInitUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, false, std::string(),
browser_context());
- new_entry->SetPageID(0);
entries.push_back(std::move(new_entry));
controller.Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -2546,7 +2536,7 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
EXPECT_FALSE(initial_host->web_ui());
// Navigation request to an entry from a previous browsing session.
- NavigationEntryImpl entry(nullptr /* instance */, 0 /* page_id */, kInitUrl,
+ NavigationEntryImpl entry(nullptr /* instance */, kInitUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_RELOAD,
false /* is_renderer_init */);
@@ -2601,7 +2591,7 @@ void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithOneWebUI(
// Navigation request to a non-WebUI page.
const GURL kUrl("http://google.com");
- NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(NULL /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -2693,7 +2683,7 @@ void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithTwoWebUIs(
// Navigation another WebUI page, with a different type.
set_webui_type(2);
const GURL kUrl("chrome://bar/");
- NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(NULL /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -2768,7 +2758,6 @@ TEST_F(RenderFrameHostManagerTest, CanCommitOrigin) {
main_test_rfh()->PrepareForCommit();
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.transition = ui::PAGE_TRANSITION_LINK;
@@ -2841,7 +2830,7 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request.
const GURL kUrl("chrome://foo");
- NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(nullptr /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -2902,7 +2891,7 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request. No change in the returned WebUI type.
const GURL kUrl("chrome://foo/bar");
- NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(nullptr /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -2960,7 +2949,7 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request.
const GURL kUrl("chrome://bar");
- NavigationEntryImpl entry(nullptr /* instance */, -1 /* page_id */, kUrl,
+ NavigationEntryImpl entry(nullptr /* instance */, kUrl,
Referrer(), base::string16() /* title */,
ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
@@ -3027,7 +3016,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
RenderFrameHostManager* child = root->child_at(0)->render_manager();
// Navigate subframe to kUrl2.
- NavigationEntryImpl entry1(nullptr /* instance */, -1 /* page_id */, kUrl2,
+ NavigationEntryImpl entry1(nullptr /* instance */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
base::string16() /* title */,
ui::PAGE_TRANSITION_LINK,
@@ -3078,7 +3067,6 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// when the child navigates.
main_test_rfh()->GetProcess()->sink().ClearMessages();
FrameHostMsg_DidCommitProvisionalLoad_Params commit_params;
- commit_params.page_id = 0;
commit_params.nav_entry_id = 0;
commit_params.did_create_new_entry = false;
commit_params.url = kUrl3;
@@ -3098,4 +3086,72 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
root->child_at(0)->current_replication_state().insecure_request_policy);
}
+// Tests that a BeginNavigation IPC from a no longer active RFH is ignored.
+TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
+ BeginNavigationIgnoredWhenNotActive) {
+ const GURL kUrl1("http://www.google.com");
+ const GURL kUrl2("http://www.chromium.org");
+ const GURL kUrl3("http://foo.com");
+
+ contents()->NavigateAndCommit(kUrl1);
+
+ TestRenderFrameHost* initial_rfh = main_test_rfh();
+ RenderViewHostDeletedObserver delete_observer(
+ initial_rfh->GetRenderViewHost());
+
+ // Navigate cross-site but don't simulate the swap out ACK. The initial RFH
+ // should be pending delete.
+ RenderFrameHostManager* manager =
+ main_test_rfh()->frame_tree_node()->render_manager();
+ contents()->StartNavigation(kUrl2);
+ static_cast<TestRenderFrameHost*>(manager->speculative_frame_host())
+ ->SimulateNavigationCommit(kUrl2);
+ EXPECT_NE(initial_rfh, main_test_rfh());
+ ASSERT_FALSE(delete_observer.deleted());
+ EXPECT_FALSE(initial_rfh->is_active());
+
+ // The initial RFH receives a BeginNavigation IPC. The navigation should not
+ // start.
+ initial_rfh->SendRendererInitiatedNavigationRequest(kUrl3, true);
+ EXPECT_FALSE(main_test_rfh()->frame_tree_node()->navigation_request());
+}
+
+// Tests that a DidStartProvisionalLoad IPC from a no longer active RFH is
+// ignored.
+TEST_F(RenderFrameHostManagerTest,
+ DidStartProvisionalLoadIgnoredWhenNotActive) {
+ if (IsBrowserSideNavigationEnabled()) {
+ SUCCEED() << "This test is not applicable to browser side navigation. See "
+ "RenderFrameHostManagerTestWithBrowserSideNavigation."
+ "BeginNavigationIgnoredWhenNotActive for a similar case when "
+ "PlzNavigate is enabled.";
+ return;
+ }
+ const GURL kUrl1("http://www.google.com");
+ const GURL kUrl2("http://www.chromium.org");
+ const GURL kUrl3("http://foo.com");
+
+ contents()->NavigateAndCommit(kUrl1);
+
+ TestRenderFrameHost* initial_rfh = main_test_rfh();
+ RenderViewHostDeletedObserver delete_observer(
+ initial_rfh->GetRenderViewHost());
+
+ // Navigate cross-site but don't simulate the swap out ACK. The initial RFH
+ // should be pending delete.
+ RenderFrameHostManager* manager =
+ main_test_rfh()->frame_tree_node()->render_manager();
+ contents()->StartNavigation(kUrl2);
+ static_cast<TestRenderFrameHost*>(manager->pending_frame_host())
+ ->SimulateNavigationCommit(kUrl2);
+ EXPECT_NE(initial_rfh, main_test_rfh());
+ ASSERT_FALSE(delete_observer.deleted());
+ EXPECT_FALSE(initial_rfh->is_active());
+
+ // The initial RFH receives a DidStartProvisionalLoad IPC. It should not
+ // create a NavigationHandle.
+ initial_rfh->SimulateNavigationStart(kUrl3);
+ EXPECT_FALSE(initial_rfh->navigation_handle());
+}
+
} // namespace content
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 fbe7febe821..573b5d9082a 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -35,6 +35,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "url/gurl.h"
+#include "url/origin.h"
#if !defined(OS_MACOSX)
#include "third_party/khronos/GLES2/gl2.h"
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 157146efa91..5ffd7b77147 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
@@ -60,8 +60,8 @@ class RenderFrameMessageFilterBrowserTest : public ContentBrowserTest {
// interacting with secure cookies.
IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, Cookies) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.AddDefaultHandlers(
@@ -123,8 +123,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, Cookies) {
// JavaScript.
IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, SameSiteCookies) {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
// The server sets five cookies on 'a.com' and on 'b.com', then loads a
// page that frames both 'a.com' and 'b.com' under 'a.com'.
@@ -174,8 +174,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
}
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(shell(),
embedded_test_server()->GetURL("/frame_with_load_event.html"));
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 43d24c79447..b8ec5d390ec 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -139,6 +139,8 @@ bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeOpener, OnDidChangeOpener)
IPC_MESSAGE_HANDLER(FrameHostMsg_AdvanceFocus, OnAdvanceFocus)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameFocused, OnFrameFocused)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SetHasReceivedUserGesture,
+ OnSetHasReceivedUserGesture)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -186,7 +188,7 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
int view_routing_id = frame_tree_node_->frame_tree()
->GetRenderViewHost(site_instance_.get())->GetRoutingID();
- RenderProcessHostImpl::GetRendererInterface(GetProcess())->CreateFrameProxy(
+ GetProcess()->GetRendererInterface()->CreateFrameProxy(
routing_id_, view_routing_id, opener_routing_id, parent_routing_id,
frame_tree_node_->current_replication_state());
@@ -258,11 +260,15 @@ void RenderFrameProxyHost::OnOpenURL(
// TODO(alexmos, creis): Figure out whether |params.user_gesture| needs to be
// passed in as well.
+ // TODO(lfg, lukasza): Remove |extra_headers| parameter from
+ // RequestTransferURL method once both RenderFrameProxyHost and
+ // RenderFrameHostImpl call RequestOpenURL from their OnOpenURL handlers.
+ // See also https://crbug.com/647772.
frame_tree_node_->navigator()->RequestTransferURL(
current_rfh, validated_url, site_instance_.get(), std::vector<GURL>(),
params.referrer, ui::PAGE_TRANSITION_LINK, GlobalRequestID(),
params.should_replace_current_entry, params.uses_post ? "POST" : "GET",
- params.resource_request_body);
+ params.resource_request_body, params.extra_headers);
}
void RenderFrameProxyHost::OnRouteMessageEvent(
@@ -372,4 +378,8 @@ void RenderFrameProxyHost::OnFrameFocused() {
frame_tree_node_, GetSiteInstance());
}
+void RenderFrameProxyHost::OnSetHasReceivedUserGesture() {
+ frame_tree_node_->current_frame_host()->SetHasReceivedUserGesture();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.h b/chromium/content/browser/frame_host/render_frame_proxy_host.h
index 8b123da3b34..2e2c57ebf16 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.h
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.h
@@ -23,7 +23,6 @@ namespace content {
class CrossProcessFrameConnector;
class FrameTreeNode;
class RenderProcessHost;
-class RenderFrameHostImpl;
class RenderViewHostImpl;
class RenderWidgetHostView;
@@ -123,6 +122,7 @@ class RenderFrameProxyHost
void OnDidChangeOpener(int32_t opener_routing_id);
void OnAdvanceFocus(blink::WebFocusType type, int32_t source_routing_id);
void OnFrameFocused();
+ void OnSetHasReceivedUserGesture();
// This RenderFrameProxyHost's routing id.
int routing_id_;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 4f8da3399f3..1831d482e57 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -33,7 +33,7 @@
#include "content/public/browser/guest_mode.h"
#include "content/public/browser/render_process_host.h"
#include "gpu/ipc/common/gpu_messages.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
@@ -62,11 +62,14 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
begin_frame_source_(nullptr),
weak_factory_(this) {
id_allocator_.reset(new cc::SurfaceIdAllocator());
- GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_);
+ auto* manager = GetSurfaceManager();
+ manager->RegisterFrameSinkId(frame_sink_id_);
+ surface_factory_ =
+ base::MakeUnique<cc::SurfaceFactory>(frame_sink_id_, manager, this);
}
RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
- if (!local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
surface_factory_->Destroy(local_frame_id_);
if (GetSurfaceManager())
@@ -85,7 +88,7 @@ void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
return;
if (frame_connector_) {
- if (!parent_frame_sink_id_.is_null()) {
+ if (parent_frame_sink_id_.is_valid()) {
GetSurfaceManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_,
frame_sink_id_);
}
@@ -109,7 +112,7 @@ void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
frame_connector_->GetParentRenderWidgetHostView();
if (parent_view) {
parent_frame_sink_id_ = parent_view->GetFrameSinkId();
- DCHECK(!parent_frame_sink_id_.is_null());
+ DCHECK(parent_frame_sink_id_.is_valid());
GetSurfaceManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
frame_sink_id_);
}
@@ -148,7 +151,7 @@ bool RenderWidgetHostViewChildFrame::HasFocus() const {
}
bool RenderWidgetHostViewChildFrame::IsSurfaceAvailableForCopy() const {
- return surface_factory_ && !local_frame_id_.is_null();
+ return local_frame_id_.is_valid();
}
void RenderWidgetHostViewChildFrame::Show() {
@@ -384,28 +387,21 @@ void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
float scale_factor = frame.metadata.device_scale_factor;
// Check whether we need to recreate the cc::Surface, which means the child
- // frame renderer has changed its output surface, or size, or scale factor.
- if (compositor_frame_sink_id != last_compositor_frame_sink_id_ &&
- surface_factory_) {
- surface_factory_->Destroy(local_frame_id_);
- surface_factory_.reset();
- }
+ // frame renderer has changed its frame sink, or size, or scale factor.
if (compositor_frame_sink_id != last_compositor_frame_sink_id_ ||
frame_size != current_surface_size_ ||
scale_factor != current_surface_scale_factor_) {
ClearCompositorSurfaceIfNecessary();
+ // If the renderer changed its frame sink, reset the surface factory to
+ // avoid returning stale resources.
+ if (compositor_frame_sink_id != last_compositor_frame_sink_id_)
+ surface_factory_->Reset();
last_compositor_frame_sink_id_ = compositor_frame_sink_id;
current_surface_size_ = frame_size;
current_surface_scale_factor_ = scale_factor;
}
- if (!surface_factory_) {
- cc::SurfaceManager* manager = GetSurfaceManager();
- surface_factory_ =
- base::MakeUnique<cc::SurfaceFactory>(frame_sink_id_, manager, this);
- }
-
- if (local_frame_id_.is_null()) {
+ if (!local_frame_id_.is_valid()) {
local_frame_id_ = id_allocator_->GenerateId();
surface_factory_->Create(local_frame_id_);
@@ -531,24 +527,34 @@ gfx::Point RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
point, cc::SurfaceId(frame_sink_id_, local_frame_id_));
}
-gfx::Point RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) {
- if (!frame_connector_ || local_frame_id_.is_null())
- return point;
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) {
+ *transformed_point = point;
+ if (!frame_connector_ || !local_frame_id_.is_valid())
+ return false;
return frame_connector_->TransformPointToLocalCoordSpace(
- point, original_surface, cc::SurfaceId(frame_sink_id_, local_frame_id_));
+ point, original_surface, cc::SurfaceId(frame_sink_id_, local_frame_id_),
+ transformed_point);
}
-gfx::Point RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
+bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) {
- if (!frame_connector_ || local_frame_id_.is_null() || target_view == this)
- return point;
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) {
+ if (!frame_connector_ || !local_frame_id_.is_valid())
+ return false;
+
+ if (target_view == this) {
+ *transformed_point = point;
+ return true;
+ }
return frame_connector_->TransformPointToCoordSpaceForView(
- point, target_view, cc::SurfaceId(frame_sink_id_, local_frame_id_));
+ point, target_view, cc::SurfaceId(frame_sink_id_, local_frame_id_),
+ transformed_point);
}
bool RenderWidgetHostViewChildFrame::IsRenderWidgetHostViewChildFrame() {
@@ -726,7 +732,7 @@ RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
}
void RenderWidgetHostViewChildFrame::ClearCompositorSurfaceIfNecessary() {
- if (surface_factory_ && !local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
surface_factory_->Destroy(local_frame_id_);
local_frame_id_ = cc::LocalFrameId();
}
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
index 66fbeeafd30..9af289d782d 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -133,12 +133,13 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void ProcessGestureEvent(const blink::WebGestureEvent& event,
const ui::LatencyInfo& latency) override;
gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point) override;
- gfx::Point TransformPointToLocalCoordSpace(
+ bool TransformPointToLocalCoordSpace(const gfx::Point& point,
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) override;
+ bool TransformPointToCoordSpaceForView(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) override;
- gfx::Point TransformPointToCoordSpaceForView(
- const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) override;
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) override;
bool IsRenderWidgetHostViewChildFrame() override;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc
index 66f84f90250..b27892cec6d 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc
@@ -28,8 +28,8 @@ class RenderWidgetHostViewChildFrameTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
void CheckScreenWidth(RenderFrameHost* render_frame_host) {
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index 62a75b44458..996f6e402a0 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -180,7 +180,7 @@ TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
cc::SurfaceId id = GetSurfaceId();
- if (!id.is_null()) {
+ if (id.is_valid()) {
#if !defined(OS_ANDROID)
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
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 712218775c0..c628e20e769 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
@@ -123,7 +123,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_frame_id_.is_null()) {
+ if (local_frame_id_.is_valid()) {
cc::SurfaceSequence sequence =
cc::SurfaceSequence(frame_sink_id_, next_surface_sequence_++);
cc::SurfaceId surface_id(frame_sink_id_, local_frame_id_);
@@ -253,6 +253,12 @@ void RenderWidgetHostViewGuest::Destroy() {
}
gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
+ // We obtain the reference to native view from the owner RenderWidgetHostView.
+ // If the guest is embedded inside a cross-process frame, it is possible to
+ // reach here after the frame is detached in which case there will be no owner
+ // view.
+ if (!GetOwnerRenderWidgetHostView())
+ return gfx::Size();
return RenderWidgetHostViewBase::GetPhysicalBackingSize();
}
@@ -287,28 +293,21 @@ void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
// Check whether we need to recreate the cc::Surface, which means the child
// frame renderer has changed its output surface, or size, or scale factor.
- if (compositor_frame_sink_id != last_compositor_frame_sink_id_ &&
- surface_factory_) {
- surface_factory_->Destroy(local_frame_id_);
- surface_factory_.reset();
- }
if (compositor_frame_sink_id != last_compositor_frame_sink_id_ ||
frame_size != current_surface_size_ ||
scale_factor != current_surface_scale_factor_ ||
(guest_ && guest_->has_attached_since_surface_set())) {
ClearCompositorSurfaceIfNecessary();
+ // If the renderer changed its frame sink, reset the surface factory to
+ // avoid returning stale resources.
+ if (compositor_frame_sink_id != last_compositor_frame_sink_id_)
+ surface_factory_->Reset();
last_compositor_frame_sink_id_ = compositor_frame_sink_id;
current_surface_size_ = frame_size;
current_surface_scale_factor_ = scale_factor;
}
- if (!surface_factory_) {
- cc::SurfaceManager* manager = GetSurfaceManager();
- surface_factory_ =
- base::MakeUnique<cc::SurfaceFactory>(frame_sink_id_, manager, this);
- }
-
- if (local_frame_id_.is_null()) {
+ if (!local_frame_id_.is_valid()) {
local_frame_id_ = id_allocator_->GenerateId();
surface_factory_->Create(local_frame_id_);
@@ -406,7 +405,7 @@ void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
if (rwhvb)
rwhvb->UpdateCursor(cursor);
} else {
- guest_->SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(
+ guest_->SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetCursor>(
guest_->browser_plugin_instance_id(), cursor));
}
}
@@ -569,11 +568,11 @@ void RenderWidgetHostViewGuest::MaybeSendSyntheticTapGesture(
gesture_tap_event.y = position.y + offset.y();
gesture_tap_event.globalX = screenPosition.x;
gesture_tap_event.globalY = screenPosition.y;
- GetOwnerRenderWidgetHostView()->ProcessGestureEvent(gesture_tap_event,
- ui::LatencyInfo());
+ GetOwnerRenderWidgetHostView()->ProcessGestureEvent(
+ gesture_tap_event, ui::LatencyInfo(ui::SourceEventType::TOUCH));
gesture_tap_event.type = blink::WebGestureEvent::GestureTapCancel;
- GetOwnerRenderWidgetHostView()->ProcessGestureEvent(gesture_tap_event,
- ui::LatencyInfo());
+ GetOwnerRenderWidgetHostView()->ProcessGestureEvent(
+ gesture_tap_event, ui::LatencyInfo(ui::SourceEventType::TOUCH));
}
}
@@ -619,7 +618,8 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
rescaled_event.deltaY /= current_device_scale_factor();
rescaled_event.wheelTicksX /= current_device_scale_factor();
rescaled_event.wheelTicksY /= current_device_scale_factor();
- host_->ForwardWheelEvent(rescaled_event);
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
+ host_->ForwardWheelEventWithLatencyInfo(rescaled_event, latency_info);
return;
}
@@ -647,8 +647,9 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
}
if (event->type == blink::WebInputEvent::MouseWheel) {
- host_->ForwardWheelEvent(
- *static_cast<const blink::WebMouseWheelEvent*>(event));
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
+ host_->ForwardWheelEventWithLatencyInfo(
+ *static_cast<const blink::WebMouseWheelEvent*>(event), latency_info);
return;
}
@@ -665,10 +666,9 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
!embedder->GetView()->HasFocus()) {
embedder->GetView()->Focus();
}
-
+ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
host_->ForwardTouchEventWithLatencyInfo(
- *static_cast<const blink::WebTouchEvent*>(event),
- ui::LatencyInfo());
+ *static_cast<const blink::WebTouchEvent*>(event), latency_info);
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 10c0ad42c87..f0b1f4de2a0 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
@@ -16,7 +16,7 @@
#include "content/browser/frame_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/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/event.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/gestures/gesture_types.h"
@@ -28,7 +28,6 @@ namespace content {
class BrowserPluginGuest;
class RenderWidgetHost;
class RenderWidgetHostImpl;
-struct NativeWebKeyboardEvent;
struct TextInputState;
// See comments in render_widget_host_view.h about this class and its members.
@@ -127,6 +126,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
InputEventAckState ack_result) override;
bool IsRenderWidgetHostViewGuest() override;
+ RenderWidgetHostViewBase* GetOwnerRenderWidgetHostView() const;
protected:
friend class RenderWidgetHostView;
@@ -137,8 +137,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
BrowserPluginGuest* guest,
base::WeakPtr<RenderWidgetHostViewBase> platform_view);
- RenderWidgetHostViewBase* GetOwnerRenderWidgetHostView() const;
-
// Since we now route GestureEvents directly to the guest renderer, we need
// a way to make sure that the BrowserPlugin in the embedder gets focused so
// that keyboard input (which still travels via BrowserPlugin) is routed to
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 b4c0f4b3cbd..94a1010738f 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
@@ -216,7 +216,7 @@ class RenderWidgetHostViewGuestSurfaceTest
DCHECK(view_);
RenderWidgetHostViewChildFrame* rwhvcf =
static_cast<RenderWidgetHostViewChildFrame*>(view_);
- if (rwhvcf->local_frame_id_.is_null())
+ if (!rwhvcf->local_frame_id_.is_valid())
return cc::SurfaceId();
return cc::SurfaceId(rwhvcf->frame_sink_id_, rwhvcf->local_frame_id_);
}
@@ -273,7 +273,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
cc::SurfaceId id = GetSurfaceId();
- if (!id.is_null()) {
+ if (id.is_valid()) {
#if !defined(OS_ANDROID)
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
@@ -296,7 +296,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
id = GetSurfaceId();
- if (!id.is_null()) {
+ if (id.is_valid()) {
#if !defined(OS_ANDROID)
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
@@ -318,7 +318,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->OnSwapCompositorFrame(
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
- EXPECT_TRUE(GetSurfaceId().is_null());
+ EXPECT_FALSE(GetSurfaceId().is_valid());
}
} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_service.h b/chromium/content/browser/gamepad/gamepad_service.h
index b7d6fbd193c..b32b42d9303 100644
--- a/chromium/content/browser/gamepad/gamepad_service.h
+++ b/chromium/content/browser/gamepad/gamepad_service.h
@@ -29,7 +29,6 @@ class GamepadProvider;
namespace content {
class GamepadServiceTestConstructor;
-class RenderProcessHost;
// Owns the GamepadProvider (the background polling thread) and keeps track of
// the number of consumers currently using the data (and pausing the provider
diff --git a/chromium/content/browser/generic_sensor_browsertest.cc b/chromium/content/browser/generic_sensor_browsertest.cc
new file mode 100644
index 00000000000..745cbfea746
--- /dev/null
+++ b/chromium/content/browser/generic_sensor_browsertest.cc
@@ -0,0 +1,136 @@
+// 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 "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_javascript_dialog_manager.h"
+#include "device/generic_sensor/platform_sensor.h"
+#include "device/generic_sensor/platform_sensor_provider.h"
+#include "device/generic_sensor/sensor_provider_impl.h"
+
+namespace content {
+
+namespace {
+
+class FakeAmbientLightSensor : public device::PlatformSensor {
+ public:
+ FakeAmbientLightSensor(device::mojom::SensorType type,
+ mojo::ScopedSharedBufferMapping mapping,
+ device::PlatformSensorProvider* provider)
+ : PlatformSensor(type, std::move(mapping), provider) {}
+
+ device::mojom::ReportingMode GetReportingMode() override {
+ return device::mojom::ReportingMode::ON_CHANGE;
+ }
+
+ bool StartSensor(
+ const device::PlatformSensorConfiguration& configuration) override {
+ device::SensorReading reading;
+ reading.timestamp =
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+ reading.values[0] = 50;
+ UpdateSensorReading(reading, true);
+ return true;
+ }
+
+ void StopSensor() override{};
+
+ protected:
+ ~FakeAmbientLightSensor() override = default;
+ bool CheckSensorConfiguration(
+ const device::PlatformSensorConfiguration& configuration) override {
+ return true;
+ }
+ device::PlatformSensorConfiguration GetDefaultConfiguration() override {
+ device::PlatformSensorConfiguration default_configuration;
+ default_configuration.set_frequency(60);
+ return default_configuration;
+ }
+};
+
+class FakeSensorProvider : public device::PlatformSensorProvider {
+ public:
+ static FakeSensorProvider* GetInstance() {
+ return base::Singleton<FakeSensorProvider, base::LeakySingletonTraits<
+ FakeSensorProvider>>::get();
+ }
+ FakeSensorProvider() = default;
+ ~FakeSensorProvider() override = default;
+
+ protected:
+ void CreateSensorInternal(device::mojom::SensorType type,
+ mojo::ScopedSharedBufferMapping mapping,
+ const CreateSensorCallback& callback) override {
+ // Create Sensors here.
+ switch (type) {
+ case device::mojom::SensorType::AMBIENT_LIGHT: {
+ scoped_refptr<device::PlatformSensor> sensor =
+ new FakeAmbientLightSensor(type, std::move(mapping), this);
+ callback.Run(std::move(sensor));
+ break;
+ }
+ default:
+ NOTIMPLEMENTED();
+ callback.Run(nullptr);
+ }
+ }
+};
+
+class GenericSensorBrowserTest : public ContentBrowserTest {
+ public:
+ GenericSensorBrowserTest()
+ : io_loop_finished_event_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {
+ // TODO(darktears): remove when the GenericSensor feature goes stable.
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitchASCII(switches::kEnableFeatures, "GenericSensor");
+ }
+
+ void SetUpOnMainThread() override {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&GenericSensorBrowserTest::SetUpOnIOThread,
+ base::Unretained(this)));
+ io_loop_finished_event_.Wait();
+ }
+
+ void SetUpOnIOThread() {
+ device::PlatformSensorProvider::SetProviderForTesting(
+ FakeSensorProvider::GetInstance());
+ io_loop_finished_event_.Signal();
+ }
+
+ void TearDown() override {
+ device::PlatformSensorProvider::SetProviderForTesting(nullptr);
+ }
+
+ public:
+ base::WaitableEvent io_loop_finished_event_;
+};
+
+IN_PROC_BROWSER_TEST_F(GenericSensorBrowserTest, AmbientLightSensorTest) {
+ // The test page will create an AmbientLightSensor object in Javascript,
+ // expects to get events with fake values then navigates to #pass.
+ GURL test_url =
+ GetTestUrl("generic_sensor", "ambient_light_sensor_test.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
index f6af12a0dfa..601a4a6c6e4 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -28,7 +28,7 @@
#include "gpu/ipc/common/gpu_messages.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/message_filter.h"
-#include "services/shell/runner/common/client_util.h"
+#include "services/service_manager/runner/common/client_util.h"
namespace content {
@@ -273,7 +273,7 @@ BrowserGpuChannelHostFactory::AllocateSharedMemory(size_t size) {
void BrowserGpuChannelHostFactory::EstablishGpuChannel(
const gpu::GpuChannelEstablishedCallback& callback) {
- DCHECK(!shell::ShellIsRemote());
+ DCHECK(!service_manager::ServiceManagerIsRemote());
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
DCHECK(!pending_request_.get());
// Recreate the channel if it has been lost.
@@ -350,10 +350,10 @@ void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"466866 BrowserGpuChannelHostFactory::GpuChannelEstablished2"));
- for (size_t n = 0; n < established_callbacks_.size(); n++)
- established_callbacks_[n].Run(gpu_channel_);
-
- established_callbacks_.clear();
+ std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks;
+ established_callbacks_.swap(established_callbacks);
+ for (auto& callback : established_callbacks)
+ callback.Run(gpu_channel_);
}
// static
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 a63fc08da1a..57170fc8049 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -288,13 +288,7 @@ void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
}
callback.Run(gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
- id, size, format, child_process_handle));
-}
-
-gfx::GpuMemoryBuffer*
-BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
- ClientBuffer buffer) {
- return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer);
+ id, size, format));
}
void BrowserGpuMemoryBufferManager::SetDestructionSyncToken(
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
index 87166e22bab..0d526d703b4 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
@@ -73,8 +73,6 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
gfx::BufferFormat format) override;
- gfx::GpuMemoryBuffer* GpuMemoryBufferFromClientBuffer(
- ClientBuffer buffer) override;
void SetDestructionSyncToken(gfx::GpuMemoryBuffer* buffer,
const gpu::SyncToken& sync_token) override;
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index e6305af5c56..f366994489d 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -26,6 +26,7 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "gpu/config/gpu_feature_type.h"
+#include "ui/gl/gl_switches.h"
namespace content {
@@ -42,6 +43,7 @@ const char kWebGLFeatureName[] = "webgl";
const char kRasterizationFeatureName[] = "rasterization";
const char kMultipleRasterThreadsFeatureName[] = "multiple_raster_threads";
const char kNativeGpuMemoryBuffersFeatureName[] = "native_gpu_memory_buffers";
+const char kWebGL2FeatureName[] = "webgl2";
const int kMinRasterThreads = 1;
const int kMaxRasterThreads = 4;
@@ -143,14 +145,20 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
"Native GpuMemoryBuffers have been disabled, either via about:flags"
" or command line.",
true},
- {"vpx_decode", manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE) ||
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
+ {"vpx_decode",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE) ||
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
accelerated_vpx_disabled,
"Accelerated VPx video decode has been disabled, either via blacklist"
" or the command line.",
true},
+ {kWebGL2FeatureName,
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2),
+ command_line.HasSwitch(switches::kDisableES3APIs),
+ "WebGL2 has been disabled via blacklist or the command line.",
+ false},
};
DCHECK(index < arraysize(kGpuFeatureInfo));
*eof = (index == arraysize(kGpuFeatureInfo) - 1);
@@ -246,10 +254,6 @@ bool IsGpuRasterizationEnabled() {
return false;
}
-#if defined(OS_ANDROID)
- return true;
-#endif
-
// Gpu Rasterization on platforms that are not fully enabled is controlled by
// a finch experiment.
return base::FeatureList::IsEnabled(features::kDefaultEnableGpuRasterization);
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 0957cf26ff1..0f517cefa26 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -4,6 +4,8 @@
#include "content/browser/gpu/gpu_data_manager_impl_private.h"
+#include <algorithm>
+#include <iterator>
#include <memory>
#include <utility>
@@ -166,23 +168,28 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING,
gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION,
- gpu::GPU_FEATURE_TYPE_WEBGL};
+ gpu::GPU_FEATURE_TYPE_WEBGL,
+ gpu::GPU_FEATURE_TYPE_WEBGL2};
const std::string kGpuBlacklistFeatureHistogramNames[] = {
"GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
"GPU.BlacklistFeatureTestResults.GpuCompositing",
"GPU.BlacklistFeatureTestResults.GpuRasterization",
- "GPU.BlacklistFeatureTestResults.Webgl"};
+ "GPU.BlacklistFeatureTestResults.Webgl",
+ "GPU.BlacklistFeatureTestResults.Webgl2"};
const bool kGpuFeatureUserFlags[] = {
command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
command_line.HasSwitch(switches::kDisableGpu),
command_line.HasSwitch(switches::kDisableGpuRasterization),
- command_line.HasSwitch(switches::kDisableExperimentalWebGL)};
+ command_line.HasSwitch(switches::kDisableExperimentalWebGL),
+ (!command_line.HasSwitch(switches::kEnableES3APIs) ||
+ command_line.HasSwitch(switches::kDisableES3APIs))};
#if defined(OS_WIN)
const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
"GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
"GPU.BlacklistFeatureTestResultsWindows.GpuCompositing",
"GPU.BlacklistFeatureTestResultsWindows.GpuRasterization",
- "GPU.BlacklistFeatureTestResultsWindows.Webgl"};
+ "GPU.BlacklistFeatureTestResultsWindows.Webgl",
+ "GPU.BlacklistFeatureTestResultsWindows.Webgl2"};
#endif
const size_t kNumFeatures =
sizeof(kGpuFeatures) / sizeof(gpu::GpuFeatureType);
@@ -342,12 +349,23 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(
// We only need to block GPU process if more features are disallowed other
// than those in the preliminary gpu feature flags because the latter work
- // through renderer commandline switches.
- std::set<int> features = preliminary_blacklisted_features_;
- gpu::MergeFeatureSets(&features, blacklisted_features_);
- if (features.size() > preliminary_blacklisted_features_.size()) {
+ // through renderer commandline switches. WebGL and WebGL2 should not matter
+ // because their context creation can always be rejected on the GPU process
+ // side.
+ std::set<int> feature_diffs;
+ std::set_difference(blacklisted_features_.begin(),
+ blacklisted_features_.end(),
+ preliminary_blacklisted_features_.begin(),
+ preliminary_blacklisted_features_.end(),
+ std::inserter(feature_diffs, feature_diffs.begin()));
+ if (feature_diffs.size()) {
+ // TODO(zmo): Other features might also be OK to ignore here.
+ feature_diffs.erase(gpu::GPU_FEATURE_TYPE_WEBGL);
+ feature_diffs.erase(gpu::GPU_FEATURE_TYPE_WEBGL2);
+ }
+ if (feature_diffs.size()) {
if (reason) {
- *reason = "Features are disabled upon full but not preliminary GPU info.";
+ *reason = "Features are disabled on full but not preliminary GPU info.";
}
return false;
}
@@ -765,6 +783,15 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
}
#endif
+ if (gpu_preferences) { // enable_es3_apis
+ bool blacklisted = IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2);
+ bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableES3APIs);
+ bool disabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableES3APIs);
+ gpu_preferences->enable_es3_apis = (enabled || !blacklisted) && !disabled;
+ }
+
// Pass GPU and driver information to GPU process. We try to avoid full GPU
// info collection at GPU process startup, but we need gpu vendor_id,
// device_id, driver_vendor, driver_version for deciding whether we need to
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 c92f37cbf43..880a83fe77f 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
@@ -193,6 +193,63 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) {
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
}
+TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklistingWebGL) {
+ // If a feature is allowed in preliminary step (browser side), but
+ // disabled when GPU process launches and collects full GPU info,
+ // it's too late to let renderer know, so we basically block all GPU
+ // access, to be on the safe side.
+ ScopedGpuDataManagerImplPrivate manager;
+ EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+ std::string reason;
+ EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+ EXPECT_TRUE(reason.empty());
+
+ const std::string blacklist_json = LONG_STRING_CONST(
+ {
+ "name": "gpu blacklist",
+ "version": "0.1",
+ "entries": [
+ {
+ "id": 1,
+ "features": [
+ "accelerated_2d_canvas"
+ ]
+ },
+ {
+ "id": 2,
+ "gl_renderer": ".*GeForce.*",
+ "features": [
+ "webgl",
+ "webgl2"
+ ]
+ }
+ ]
+ }
+ );
+
+ gpu::GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0640;
+ manager->InitializeForTesting(blacklist_json, gpu_info);
+
+ EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+ EXPECT_TRUE(reason.empty());
+ EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+ EXPECT_TRUE(manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
+
+ gpu_info.gl_vendor = "NVIDIA";
+ gpu_info.gl_renderer = "NVIDIA GeForce GT 120";
+ manager->UpdateGpuInfo(gpu_info);
+ EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+ EXPECT_TRUE(reason.empty());
+ EXPECT_EQ(3u, manager->GetBlacklistedFeatureCount());
+ EXPECT_TRUE(manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
+ EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
+ EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2));
+}
+
TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) {
ScopedGpuDataManagerImplPrivate manager;
EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index d2a183a83e7..d4fbb8eac7e 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -54,7 +54,7 @@
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/ipc/service/switches.h"
@@ -62,9 +62,9 @@
#include "ipc/message_filter.h"
#include "media/base/media_switches.h"
#include "mojo/edk/embedder/embedder.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/runner/common/client_util.h"
+#include "services/service_manager/public/cpp/connection.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/events/latency_info.h"
#include "ui/gl/gl_switches.h"
@@ -92,7 +92,7 @@
#endif
#if defined(OS_MACOSX) || defined(OS_ANDROID)
-#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "gpu/ipc/common/gpu_surface_tracker.h"
#endif
namespace content {
@@ -111,6 +111,7 @@ static const char* const kSwitchNames[] = {
switches::kCreateDefaultGLContext,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBreakpad,
+ switches::kDisableES3GLContext,
switches::kDisableGpuSandbox,
switches::kDisableGpuWatchdog,
switches::kDisableGLExtensions,
@@ -146,6 +147,7 @@ static const char* const kSwitchNames[] = {
switches::kV,
switches::kVModule,
#if defined(OS_MACOSX)
+ switches::kDisableAVFoundationOverlays,
switches::kDisableRemoteCoreAnimation,
switches::kEnableSandboxLogging,
switches::kShowMacOverlayBorders,
@@ -200,13 +202,12 @@ void SendGpuProcessMessageByHostId(int host_id, IPC::Message* message) {
class GpuSandboxedProcessLauncherDelegate
: public SandboxedProcessLauncherDelegate {
public:
- GpuSandboxedProcessLauncherDelegate(base::CommandLine* cmd_line,
- ChildProcessHost* host)
+ explicit GpuSandboxedProcessLauncherDelegate(base::CommandLine* cmd_line)
#if defined(OS_WIN)
- : cmd_line_(cmd_line) {}
-#elif defined(OS_POSIX)
- : ipc_fd_(host->TakeClientFileDescriptor()) {}
+ : cmd_line_(cmd_line)
#endif
+ {
+ }
~GpuSandboxedProcessLauncherDelegate() override {}
@@ -287,9 +288,6 @@ class GpuSandboxedProcessLauncherDelegate
return true;
}
-#elif defined(OS_POSIX)
-
- base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
SandboxType GetSandboxType() override {
@@ -299,11 +297,17 @@ class GpuSandboxedProcessLauncherDelegate
private:
#if defined(OS_WIN)
base::CommandLine* cmd_line_;
-#elif defined(OS_POSIX)
- base::ScopedFD ipc_fd_;
#endif // OS_WIN
};
+void HostLoadedShader(int host_id,
+ const std::string& key,
+ const std::string& data) {
+ GpuProcessHost* host = GpuProcessHost::FromID(host_id);
+ if (host)
+ host->LoadedShader(key, data);
+}
+
} // anonymous namespace
class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
@@ -312,10 +316,10 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
private:
// ConnectionFilter:
- bool OnConnect(const shell::Identity& remote_identity,
- shell::InterfaceRegistry* registry,
- shell::Connector* connector) override {
- if (remote_identity.name() != kGpuServiceName)
+ bool OnConnect(const service_manager::Identity& remote_identity,
+ service_manager::InterfaceRegistry* registry,
+ service_manager::Connector* connector) override {
+ if (remote_identity.name() != mojom::kGpuServiceName)
return false;
GetContentClient()->browser()->ExposeInterfacesToGpuProcess(registry,
@@ -348,7 +352,7 @@ bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
// static
GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, bool force_create) {
- DCHECK(!shell::ShellIsRemote());
+ DCHECK(!service_manager::ServiceManagerIsRemote());
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Don't grant further access to GPU if it is not allowed.
@@ -428,7 +432,7 @@ void GpuProcessHost::RegisterGpuMainThreadFactory(
g_gpu_main_thread_factory = create;
}
-shell::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() {
+service_manager::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() {
return process_->child_connection()->GetRemoteInterfaces();
}
@@ -477,7 +481,7 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id));
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_GPU, this, kGpuServiceName));
+ PROCESS_TYPE_GPU, this, mojom::kGpuServiceName));
}
GpuProcessHost::~GpuProcessHost() {
@@ -498,7 +502,7 @@ GpuProcessHost::~GpuProcessHost() {
#if defined(OS_MACOSX) || defined(OS_ANDROID)
UMA_HISTOGRAM_COUNTS_100("GPU.AtExitSurfaceCount",
- GpuSurfaceTracker::Get()->GetSurfaceCount());
+ gpu::GpuSurfaceTracker::Get()->GetSurfaceCount());
#endif
std::string message;
@@ -993,7 +997,9 @@ bool GpuProcessHost::LaunchGpuProcess(gpu::GpuPreferences* gpu_preferences) {
base::CommandLine* cmd_line = new base::CommandLine(exe_path);
#endif
+
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
+
BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line);
#if defined(OS_WIN)
@@ -1037,11 +1043,8 @@ bool GpuProcessHost::LaunchGpuProcess(gpu::GpuPreferences* gpu_preferences) {
if (!gpu_launcher.empty())
cmd_line->PrependWrapper(gpu_launcher);
- process_->Launch(
- new GpuSandboxedProcessLauncherDelegate(cmd_line,
- process_->GetHost()),
- cmd_line,
- true);
+ process_->Launch(new GpuSandboxedProcessLauncherDelegate(cmd_line), cmd_line,
+ true);
process_launched_ = true;
UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
@@ -1171,7 +1174,7 @@ void GpuProcessHost::CreateChannelCache(int32_t client_id) {
if (!cache.get())
return;
- cache->set_host_id(host_id_);
+ cache->set_shader_loaded_callback(base::Bind(&HostLoadedShader, host_id_));
client_id_to_shader_cache_[client_id] = cache;
}
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index d42c354f7bf..50172364920 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -32,8 +32,6 @@
#include "ui/gfx/gpu_memory_buffer.h"
#include "url/gurl.h"
-struct GPUCreateCommandBufferConfig;
-
namespace base {
class Thread;
}
@@ -47,7 +45,7 @@ struct GpuPreferences;
struct SyncToken;
}
-namespace shell {
+namespace service_manager {
class InterfaceProvider;
}
@@ -55,7 +53,6 @@ namespace content {
class BrowserChildProcessHostImpl;
class GpuMainThread;
class InProcessChildThreadParams;
-class RenderWidgetHostViewFrameSubscriber;
class ShaderDiskCache;
typedef base::Thread* (*GpuMainThreadFactoryFunction)(
@@ -113,7 +110,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
CONTENT_EXPORT static void RegisterGpuMainThreadFactory(
GpuMainThreadFactoryFunction create);
- shell::InterfaceProvider* GetRemoteInterfaces();
+ service_manager::InterfaceProvider* GetRemoteInterfaces();
// Get the GPU process host for the GPU process with the given ID. Returns
// null if the process no longer exists.
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
index fa2225800d7..1f05ece1564 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
@@ -27,14 +27,6 @@
#include "ipc/ipc_sender.h"
#include "ipc/message_router.h"
-namespace ui {
-class LatencyInfo;
-}
-
-namespace gfx {
-class Size;
-}
-
namespace IPC {
class Message;
}
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.cc b/chromium/content/browser/gpu/gpu_surface_tracker.cc
deleted file mode 100644
index 3c6754c4ba9..00000000000
--- a/chromium/content/browser/gpu/gpu_surface_tracker.cc
+++ /dev/null
@@ -1,76 +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/gpu/gpu_surface_tracker.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-#if defined(OS_ANDROID)
-#include <android/native_window_jni.h>
-#include "content/browser/android/child_process_launcher_android.h"
-#include "ui/gl/android/scoped_java_surface.h"
-#endif // defined(OS_ANDROID)
-
-namespace content {
-
-GpuSurfaceTracker::GpuSurfaceTracker()
- : next_surface_handle_(1) {
- gpu::GpuSurfaceLookup::InitInstance(this);
-}
-
-GpuSurfaceTracker::~GpuSurfaceTracker() {
- gpu::GpuSurfaceLookup::InitInstance(NULL);
-}
-
-GpuSurfaceTracker* GpuSurfaceTracker::GetInstance() {
- return base::Singleton<GpuSurfaceTracker>::get();
-}
-
-int GpuSurfaceTracker::AddSurfaceForNativeWidget(
- gfx::AcceleratedWidget widget) {
- base::AutoLock lock(lock_);
- gpu::SurfaceHandle surface_handle = next_surface_handle_++;
- surface_map_[surface_handle] = widget;
- return surface_handle;
-}
-
-bool GpuSurfaceTracker::IsValidSurfaceHandle(
- gpu::SurfaceHandle surface_handle) const {
- return surface_map_.find(surface_handle) != surface_map_.end();
-}
-
-void GpuSurfaceTracker::RemoveSurface(gpu::SurfaceHandle surface_handle) {
- base::AutoLock lock(lock_);
- DCHECK(surface_map_.find(surface_handle) != surface_map_.end());
- surface_map_.erase(surface_handle);
-}
-
-gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(
- gpu::SurfaceHandle surface_handle) {
- base::AutoLock lock(lock_);
- SurfaceMap::iterator it = surface_map_.find(surface_handle);
- if (it == surface_map_.end())
- return gfx::kNullAcceleratedWidget;
-
-#if defined(OS_ANDROID)
- if (it->second != gfx::kNullAcceleratedWidget)
- ANativeWindow_acquire(it->second);
-#endif // defined(OS_ANDROID)
-
- return it->second;
-}
-
-#if defined(OS_ANDROID)
-gl::ScopedJavaSurface GpuSurfaceTracker::AcquireJavaSurface(int surface_id) {
- return GetViewSurface(surface_id);
-}
-#endif
-
-std::size_t GpuSurfaceTracker::GetSurfaceCount() {
- base::AutoLock lock(lock_);
- return surface_map_.size();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.h b/chromium/content/browser/gpu/gpu_surface_tracker.h
deleted file mode 100644
index 0d55b327b60..00000000000
--- a/chromium/content/browser/gpu/gpu_surface_tracker.h
+++ /dev/null
@@ -1,81 +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_GPU_GPU_SURFACE_TRACKER_H_
-#define CONTENT_BROWSER_GPU_GPU_SURFACE_TRACKER_H_
-
-#include <stddef.h>
-
-#include <map>
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "gpu/ipc/common/gpu_surface_lookup.h"
-#include "gpu/ipc/common/surface_handle.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-
-// This class is used on Android and Mac, and is responsible for tracking native
-// window surfaces exposed to the GPU process. Every surface gets registered to
-// this class, and gets a handle. The handle can be passed to
-// CommandBufferProxyImpl::Create or to
-// GpuMemoryBufferManager::AllocateGpuMemoryBuffer.
-// On Android, the handle is used in the GPU process to get a reference to the
-// ANativeWindow, using GpuSurfaceLookup (implemented by
-// SurfaceTextureManagerImpl).
-// On Mac, the handle just passes through the GPU process, and is sent back via
-// GpuCommandBufferMsg_SwapBuffersCompleted to reference the surface.
-// This class is thread safe.
-class CONTENT_EXPORT GpuSurfaceTracker : public gpu::GpuSurfaceLookup {
- public:
- // GpuSurfaceLookup implementation:
- // Returns the native widget associated with a given surface_handle.
- // On Android, this adds a reference on the ANativeWindow.
- gfx::AcceleratedWidget AcquireNativeWidget(
- gpu::SurfaceHandle surface_handle) override;
-
-#if defined(OS_ANDROID)
- gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override;
-#endif
-
- // Gets the global instance of the surface tracker.
- static GpuSurfaceTracker* Get() { return GetInstance(); }
-
- // Adds a surface for a native widget. Returns the surface ID.
- int AddSurfaceForNativeWidget(gfx::AcceleratedWidget widget);
-
- // Return true if the surface handle is registered with the tracker.
- bool IsValidSurfaceHandle(gpu::SurfaceHandle surface_handle) const;
-
- // Removes a given existing surface.
- void RemoveSurface(gpu::SurfaceHandle surface_handle);
-
- // Returns the number of surfaces currently registered with the tracker.
- std::size_t GetSurfaceCount();
-
- // Gets the global instance of the surface tracker. Identical to Get(), but
- // named that way for the implementation of Singleton.
- static GpuSurfaceTracker* GetInstance();
-
- private:
- typedef std::map<gpu::SurfaceHandle, gfx::AcceleratedWidget> SurfaceMap;
-
- friend struct base::DefaultSingletonTraits<GpuSurfaceTracker>;
-
- GpuSurfaceTracker();
- ~GpuSurfaceTracker() override;
-
- base::Lock lock_;
- SurfaceMap surface_map_;
- int next_surface_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuSurfaceTracker);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GPU_GPU_SURFACE_TRACKER_H_
diff --git a/chromium/content/browser/gpu/shader_disk_cache.cc b/chromium/content/browser/gpu/shader_disk_cache.cc
index f75fe838808..a609b85a237 100644
--- a/chromium/content/browser/gpu/shader_disk_cache.cc
+++ b/chromium/content/browser/gpu/shader_disk_cache.cc
@@ -5,9 +5,9 @@
#include "content/browser/gpu/shader_disk_cache.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/common/constants.h"
#include "net/base/cache_type.h"
#include "net/base/io_buffer.h"
@@ -20,65 +20,57 @@ namespace {
static const base::FilePath::CharType kGpuCachePath[] =
FILE_PATH_LITERAL("GPUCache");
-void EntryCloser(disk_cache::Entry* entry) {
- entry->Close();
-}
-
-void FreeDiskCacheIterator(
- std::unique_ptr<disk_cache::Backend::Iterator> iterator) {}
+static ShaderCacheFactory* factory_instance = nullptr;
} // namespace
// ShaderDiskCacheEntry handles the work of caching/updating the cached
// shaders.
-class ShaderDiskCacheEntry
- : public base::ThreadChecker,
- public base::RefCounted<ShaderDiskCacheEntry> {
+class ShaderDiskCacheEntry : public base::ThreadChecker {
public:
- ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache,
+ ShaderDiskCacheEntry(ShaderDiskCache* cache,
const std::string& key,
const std::string& shader);
+ ~ShaderDiskCacheEntry();
+
void Cache();
private:
- friend class base::RefCounted<ShaderDiskCacheEntry>;
-
enum OpType {
- TERMINATE,
OPEN_ENTRY,
WRITE_DATA,
CREATE_ENTRY,
};
- ~ShaderDiskCacheEntry();
-
void OnOpComplete(int rv);
int OpenCallback(int rv);
int WriteCallback(int rv);
int IOComplete(int rv);
- base::WeakPtr<ShaderDiskCache> cache_;
+ ShaderDiskCache* cache_;
OpType op_type_;
std::string key_;
std::string shader_;
disk_cache::Entry* entry_;
+ base::WeakPtr<ShaderDiskCacheEntry> weak_ptr_;
+ base::WeakPtrFactory<ShaderDiskCacheEntry> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry);
};
// ShaderDiskReadHelper is used to load all of the cached shaders from the
// disk cache and send to the memory cache.
-class ShaderDiskReadHelper
- : public base::ThreadChecker,
- public base::RefCounted<ShaderDiskReadHelper> {
+class ShaderDiskReadHelper : public base::ThreadChecker {
public:
- ShaderDiskReadHelper(base::WeakPtr<ShaderDiskCache> cache, int host_id);
+ using ShaderLoadedCallback = ShaderDiskCache::ShaderLoadedCallback;
+ ShaderDiskReadHelper(ShaderDiskCache* cache,
+ const ShaderLoadedCallback& callback);
+ ~ShaderDiskReadHelper();
+
void LoadCache();
private:
- friend class base::RefCounted<ShaderDiskReadHelper>;
-
enum OpType {
TERMINATE,
OPEN_NEXT,
@@ -88,8 +80,6 @@ class ShaderDiskReadHelper
};
- ~ShaderDiskReadHelper();
-
void OnOpComplete(int rv);
int OpenNextEntry();
@@ -97,38 +87,35 @@ class ShaderDiskReadHelper
int ReadComplete(int rv);
int IterationComplete(int rv);
- base::WeakPtr<ShaderDiskCache> cache_;
+ ShaderDiskCache* cache_;
+ ShaderLoadedCallback shader_loaded_callback_;
OpType op_type_;
std::unique_ptr<disk_cache::Backend::Iterator> iter_;
scoped_refptr<net::IOBufferWithSize> buf_;
- int host_id_;
disk_cache::Entry* entry_;
+ base::WeakPtrFactory<ShaderDiskReadHelper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper);
};
-class ShaderClearHelper
- : public base::RefCounted<ShaderClearHelper>,
- public base::SupportsWeakPtr<ShaderClearHelper> {
+class ShaderClearHelper : public base::ThreadChecker {
public:
ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
const base::FilePath& path,
const base::Time& delete_begin,
const base::Time& delete_end,
const base::Closure& callback);
+ ~ShaderClearHelper();
+
void Clear();
private:
- friend class base::RefCounted<ShaderClearHelper>;
-
enum OpType {
TERMINATE,
VERIFY_CACHE_SETUP,
DELETE_CACHE
};
- ~ShaderClearHelper();
-
void DoClearShaderCache(int rv);
scoped_refptr<ShaderDiskCache> cache_;
@@ -137,44 +124,47 @@ class ShaderClearHelper
base::Time delete_begin_;
base::Time delete_end_;
base::Closure callback_;
+ base::WeakPtrFactory<ShaderClearHelper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper);
};
-ShaderDiskCacheEntry::ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache,
+////////////////////////////////////////////////////////////////////////////////
+// ShaderDiskCacheEntry
+
+ShaderDiskCacheEntry::ShaderDiskCacheEntry(ShaderDiskCache* cache,
const std::string& key,
const std::string& shader)
- : cache_(cache),
- op_type_(OPEN_ENTRY),
- key_(key),
- shader_(shader),
- entry_(NULL) {
+ : cache_(cache),
+ op_type_(OPEN_ENTRY),
+ key_(key),
+ shader_(shader),
+ entry_(nullptr),
+ weak_ptr_factory_(this) {
+ weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
}
ShaderDiskCacheEntry::~ShaderDiskCacheEntry() {
+ DCHECK(CalledOnValidThread());
if (entry_)
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&EntryCloser, entry_));
+ entry_->Close();
}
void ShaderDiskCacheEntry::Cache() {
DCHECK(CalledOnValidThread());
- if (!cache_.get())
- return;
-
int rv = cache_->backend()->OpenEntry(
- key_,
- &entry_,
- base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this));
+ key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
+ weak_ptr_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
OnOpComplete(rv);
}
void ShaderDiskCacheEntry::OnOpComplete(int rv) {
DCHECK(CalledOnValidThread());
- if (!cache_.get())
- return;
-
+ // The function calls inside the switch block below can end up destroying
+ // |this|. So hold on to a WeakPtr<>, and terminate the while loop if |this|
+ // has been destroyed.
+ auto weak_ptr = std::move(weak_ptr_);
do {
switch (op_type_) {
case OPEN_ENTRY:
@@ -186,84 +176,74 @@ void ShaderDiskCacheEntry::OnOpComplete(int rv) {
case WRITE_DATA:
rv = IOComplete(rv);
break;
- case TERMINATE:
- rv = net::ERR_IO_PENDING; // break the loop.
- break;
- default:
- NOTREACHED(); // Invalid op_type_ provided.
- break;
}
- } while (rv != net::ERR_IO_PENDING);
+ } while (rv != net::ERR_IO_PENDING && weak_ptr);
+ if (weak_ptr)
+ weak_ptr_ = std::move(weak_ptr);
}
int ShaderDiskCacheEntry::OpenCallback(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
if (rv == net::OK) {
cache_->backend()->OnExternalCacheHit(key_);
cache_->EntryComplete(this);
- op_type_ = TERMINATE;
return rv;
}
op_type_ = CREATE_ENTRY;
return cache_->backend()->CreateEntry(
- key_,
- &entry_,
- base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this));
+ key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
+ weak_ptr_factory_.GetWeakPtr()));
}
int ShaderDiskCacheEntry::WriteCallback(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
if (rv != net::OK) {
LOG(ERROR) << "Failed to create shader cache entry: " << rv;
cache_->EntryComplete(this);
- op_type_ = TERMINATE;
return rv;
}
op_type_ = WRITE_DATA;
scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_);
- return entry_->WriteData(
- 1,
- 0,
- io_buf.get(),
- shader_.length(),
- base::Bind(&ShaderDiskCacheEntry::OnOpComplete, this),
- false);
+ return entry_->WriteData(1, 0, io_buf.get(), shader_.length(),
+ base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
+ weak_ptr_factory_.GetWeakPtr()),
+ false);
}
int ShaderDiskCacheEntry::IOComplete(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
cache_->EntryComplete(this);
- op_type_ = TERMINATE;
return rv;
}
-ShaderDiskReadHelper::ShaderDiskReadHelper(
- base::WeakPtr<ShaderDiskCache> cache,
- int host_id)
+////////////////////////////////////////////////////////////////////////////////
+// ShaderDiskReadHelper
+
+ShaderDiskReadHelper::ShaderDiskReadHelper(ShaderDiskCache* cache,
+ const ShaderLoadedCallback& callback)
: cache_(cache),
+ shader_loaded_callback_(callback),
op_type_(OPEN_NEXT),
buf_(NULL),
- host_id_(host_id),
- entry_(NULL) {
+ entry_(NULL),
+ weak_ptr_factory_(this) {}
+
+ShaderDiskReadHelper::~ShaderDiskReadHelper() {
+ DCHECK(CalledOnValidThread());
+ if (entry_)
+ entry_->Close();
+ iter_ = nullptr;
}
void ShaderDiskReadHelper::LoadCache() {
DCHECK(CalledOnValidThread());
- if (!cache_.get())
- return;
OnOpComplete(net::OK);
}
void ShaderDiskReadHelper::OnOpComplete(int rv) {
DCHECK(CalledOnValidThread());
- if (!cache_.get())
- return;
-
do {
switch (op_type_) {
case OPEN_NEXT:
@@ -282,27 +262,22 @@ void ShaderDiskReadHelper::OnOpComplete(int rv) {
cache_->ReadComplete();
rv = net::ERR_IO_PENDING; // break the loop
break;
- default:
- NOTREACHED(); // Invalid state for read helper
- rv = net::ERR_FAILED;
- break;
}
} while (rv != net::ERR_IO_PENDING);
}
int ShaderDiskReadHelper::OpenNextEntry() {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
op_type_ = OPEN_NEXT_COMPLETE;
if (!iter_)
iter_ = cache_->backend()->CreateIterator();
- return iter_->OpenNextEntry(
- &entry_, base::Bind(&ShaderDiskReadHelper::OnOpComplete, this));
+ return iter_->OpenNextEntry(&entry_,
+ base::Bind(&ShaderDiskReadHelper::OnOpComplete,
+ weak_ptr_factory_.GetWeakPtr()));
}
int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
if (rv == net::ERR_FAILED) {
iter_.reset();
op_type_ = ITERATION_FINISHED;
@@ -314,22 +289,16 @@ int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) {
op_type_ = READ_COMPLETE;
buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1));
- return entry_->ReadData(
- 1,
- 0,
- buf_.get(),
- buf_->size(),
- base::Bind(&ShaderDiskReadHelper::OnOpComplete, this));
+ return entry_->ReadData(1, 0, buf_.get(), buf_->size(),
+ base::Bind(&ShaderDiskReadHelper::OnOpComplete,
+ weak_ptr_factory_.GetWeakPtr()));
}
int ShaderDiskReadHelper::ReadComplete(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
- if (rv && rv == buf_->size()) {
- GpuProcessHost* host = GpuProcessHost::FromID(host_id_);
- if (host)
- host->LoadedShader(entry_->GetKey(), std::string(buf_->data(),
- buf_->size()));
+ if (rv && rv == buf_->size() && !shader_loaded_callback_.is_null()) {
+ shader_loaded_callback_.Run(entry_->GetKey(),
+ std::string(buf_->data(), buf_->size()));
}
buf_ = NULL;
@@ -342,103 +311,112 @@ int ShaderDiskReadHelper::ReadComplete(int rv) {
int ShaderDiskReadHelper::IterationComplete(int rv) {
DCHECK(CalledOnValidThread());
- // Called through OnOpComplete, so we know |cache_| is valid.
iter_.reset();
op_type_ = TERMINATE;
return net::OK;
}
-ShaderDiskReadHelper::~ShaderDiskReadHelper() {
- if (entry_) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&EntryCloser, entry_));
- }
- if (iter_) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&FreeDiskCacheIterator,
- base::Passed(&iter_)));
- }
-}
+////////////////////////////////////////////////////////////////////////////////
+// ShaderClearHelper
ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
- const base::FilePath& path,
- const base::Time& delete_begin,
- const base::Time& delete_end,
- const base::Closure& callback)
- : cache_(cache),
+ const base::FilePath& path,
+ const base::Time& delete_begin,
+ const base::Time& delete_end,
+ const base::Closure& callback)
+ : cache_(std::move(cache)),
op_type_(VERIFY_CACHE_SETUP),
path_(path),
delete_begin_(delete_begin),
delete_end_(delete_end),
- callback_(callback) {
-}
+ callback_(callback),
+ weak_ptr_factory_(this) {}
ShaderClearHelper::~ShaderClearHelper() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(CalledOnValidThread());
}
void ShaderClearHelper::Clear() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(CalledOnValidThread());
DoClearShaderCache(net::OK);
}
void ShaderClearHelper::DoClearShaderCache(int rv) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Hold a ref to ourselves so when we do the CacheCleared call we don't get
- // auto-deleted when our ref count drops to zero.
- scoped_refptr<ShaderClearHelper> helper = this;
-
+ DCHECK(CalledOnValidThread());
while (rv != net::ERR_IO_PENDING) {
switch (op_type_) {
case VERIFY_CACHE_SETUP:
rv = cache_->SetAvailableCallback(
- base::Bind(&ShaderClearHelper::DoClearShaderCache, AsWeakPtr()));
+ base::Bind(&ShaderClearHelper::DoClearShaderCache,
+ weak_ptr_factory_.GetWeakPtr()));
op_type_ = DELETE_CACHE;
break;
case DELETE_CACHE:
- rv = cache_->Clear(
- delete_begin_, delete_end_,
- base::Bind(&ShaderClearHelper::DoClearShaderCache, AsWeakPtr()));
+ rv = cache_->Clear(delete_begin_, delete_end_,
+ base::Bind(&ShaderClearHelper::DoClearShaderCache,
+ weak_ptr_factory_.GetWeakPtr()));
op_type_ = TERMINATE;
break;
case TERMINATE:
- ShaderCacheFactory::GetInstance()->CacheCleared(path_);
callback_.Run();
+ // Calling CacheCleared() destroys |this|.
+ ShaderCacheFactory::GetInstance()->CacheCleared(path_);
rv = net::ERR_IO_PENDING; // Break the loop.
break;
- default:
- NOTREACHED(); // Invalid state provided.
- op_type_ = TERMINATE;
- break;
}
}
}
+////////////////////////////////////////////////////////////////////////////////
+// ShaderCacheFactory
+
+// static
+void ShaderCacheFactory::InitInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+ if (task_runner->BelongsToCurrentThread()) {
+ CreateFactoryInstance(std::move(cache_task_runner));
+ } else {
+ task_runner->PostTask(FROM_HERE,
+ base::Bind(&ShaderCacheFactory::CreateFactoryInstance,
+ std::move(cache_task_runner)));
+ }
+}
+
// static
ShaderCacheFactory* ShaderCacheFactory::GetInstance() {
- return base::Singleton<ShaderCacheFactory,
- base::LeakySingletonTraits<ShaderCacheFactory>>::get();
+ DCHECK(!factory_instance || factory_instance->CalledOnValidThread());
+ return factory_instance;
}
-ShaderCacheFactory::ShaderCacheFactory() {
-}
+ShaderCacheFactory::ShaderCacheFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner)
+ : cache_task_runner_(std::move(cache_task_runner)) {}
ShaderCacheFactory::~ShaderCacheFactory() {
}
+// static
+void ShaderCacheFactory::CreateFactoryInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+ DCHECK(!factory_instance);
+ factory_instance = new ShaderCacheFactory(std::move(cache_task_runner));
+}
+
void ShaderCacheFactory::SetCacheInfo(int32_t client_id,
const base::FilePath& path) {
+ DCHECK(CalledOnValidThread());
client_id_to_path_map_[client_id] = path;
}
void ShaderCacheFactory::RemoveCacheInfo(int32_t client_id) {
+ DCHECK(CalledOnValidThread());
client_id_to_path_map_.erase(client_id);
}
scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32_t client_id) {
- ClientIdToPathMap::iterator iter =
- client_id_to_path_map_.find(client_id);
+ DCHECK(CalledOnValidThread());
+ ClientIdToPathMap::iterator iter = client_id_to_path_map_.find(client_id);
if (iter == client_id_to_path_map_.end())
return NULL;
return ShaderCacheFactory::GetByPath(iter->second);
@@ -446,21 +424,24 @@ scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32_t client_id) {
scoped_refptr<ShaderDiskCache> ShaderCacheFactory::GetByPath(
const base::FilePath& path) {
+ DCHECK(CalledOnValidThread());
ShaderCacheMap::iterator iter = shader_cache_map_.find(path);
if (iter != shader_cache_map_.end())
return iter->second;
ShaderDiskCache* cache = new ShaderDiskCache(path);
- cache->Init();
+ cache->Init(cache_task_runner_);
return cache;
}
void ShaderCacheFactory::AddToCache(const base::FilePath& key,
ShaderDiskCache* cache) {
+ DCHECK(CalledOnValidThread());
shader_cache_map_[key] = cache;
}
void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) {
+ DCHECK(CalledOnValidThread());
shader_cache_map_.erase(key);
}
@@ -468,10 +449,10 @@ void ShaderCacheFactory::ClearByPath(const base::FilePath& path,
const base::Time& delete_begin,
const base::Time& delete_end,
const base::Closure& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(CalledOnValidThread());
DCHECK(!callback.is_null());
- scoped_refptr<ShaderClearHelper> helper = new ShaderClearHelper(
+ auto helper = base::MakeUnique<ShaderClearHelper>(
GetByPath(path), path, delete_begin, delete_end, callback);
// We could receive requests to clear the same path with different
@@ -481,18 +462,21 @@ void ShaderCacheFactory::ClearByPath(const base::FilePath& path,
// list and wait for any previous clears to finish.
ShaderClearMap::iterator iter = shader_clear_map_.find(path);
if (iter != shader_clear_map_.end()) {
- iter->second.push(helper);
+ iter->second.push(std::move(helper));
return;
}
+ // Insert the helper in the map before calling Clear(), since it can lead to a
+ // call back into CacheCleared().
+ ShaderClearHelper* helper_ptr = helper.get();
shader_clear_map_.insert(
std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue()));
- shader_clear_map_[path].push(helper);
- helper->Clear();
+ shader_clear_map_[path].push(std::move(helper));
+ helper_ptr->Clear();
}
void ShaderCacheFactory::CacheCleared(const base::FilePath& path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(CalledOnValidThread());
ShaderClearMap::iterator iter = shader_clear_map_.find(path);
if (iter == shader_clear_map_.end()) {
@@ -509,12 +493,14 @@ void ShaderCacheFactory::CacheCleared(const base::FilePath& path) {
return;
}
- shader_clear_map_.erase(path);
+ shader_clear_map_.erase(iter);
}
+////////////////////////////////////////////////////////////////////////////////
+// ShaderDiskCache
+
ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path)
: cache_available_(false),
- host_id_(0),
cache_path_(cache_path),
is_initialized_(false) {
ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this);
@@ -524,7 +510,8 @@ ShaderDiskCache::~ShaderDiskCache() {
ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_);
}
-void ShaderDiskCache::Init() {
+void ShaderDiskCache::Init(
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
if (is_initialized_) {
NOTREACHED(); // can't initialize disk cache twice.
return;
@@ -534,8 +521,7 @@ void ShaderDiskCache::Init() {
int rv = disk_cache::CreateCacheBackend(
net::SHADER_CACHE, net::CACHE_BACKEND_DEFAULT,
cache_path_.Append(kGpuCachePath),
- gpu::kDefaultMaxProgramCacheMemoryBytes, true,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE).get(), NULL,
+ gpu::kDefaultMaxProgramCacheMemoryBytes, true, cache_task_runner, NULL,
&backend_, base::Bind(&ShaderDiskCache::CacheCreatedCallback, this));
if (rv == net::OK)
@@ -546,11 +532,10 @@ void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) {
if (!cache_available_)
return;
- scoped_refptr<ShaderDiskCacheEntry> shim =
- new ShaderDiskCacheEntry(AsWeakPtr(), key, shader);
+ auto shim = base::MakeUnique<ShaderDiskCacheEntry>(this, key, shader);
shim->Cache();
-
- entry_map_[shim.get()] = shim;
+ auto* raw_ptr = shim.get();
+ entries_.insert(std::make_pair(raw_ptr, std::move(shim)));
}
int ShaderDiskCache::Clear(
@@ -585,19 +570,19 @@ void ShaderDiskCache::CacheCreatedCallback(int rv) {
LOG(ERROR) << "Shader Cache Creation failed: " << rv;
return;
}
- helper_ = new ShaderDiskReadHelper(AsWeakPtr(), host_id_);
+ helper_ =
+ base::MakeUnique<ShaderDiskReadHelper>(this, shader_loaded_callback_);
helper_->LoadCache();
}
-void ShaderDiskCache::EntryComplete(void* entry) {
- entry_map_.erase(entry);
-
- if (entry_map_.empty() && !cache_complete_callback_.is_null())
+void ShaderDiskCache::EntryComplete(ShaderDiskCacheEntry* entry) {
+ entries_.erase(entry);
+ if (entries_.empty() && !cache_complete_callback_.is_null())
cache_complete_callback_.Run(net::OK);
}
void ShaderDiskCache::ReadComplete() {
- helper_ = NULL;
+ helper_ = nullptr;
// The cache is considered available after we have finished reading any
// of the old cache values off disk. This prevents a potential race where we
@@ -611,7 +596,7 @@ void ShaderDiskCache::ReadComplete() {
int ShaderDiskCache::SetCacheCompleteCallback(
const net::CompletionCallback& callback) {
- if (entry_map_.empty()) {
+ if (entries_.empty()) {
return net::OK;
}
cache_complete_callback_ = callback;
diff --git a/chromium/content/browser/gpu/shader_disk_cache.h b/chromium/content/browser/gpu/shader_disk_cache.h
index e86b4e6df69..dbe7ef0c837 100644
--- a/chromium/content/browser/gpu/shader_disk_cache.h
+++ b/chromium/content/browser/gpu/shader_disk_cache.h
@@ -14,7 +14,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "net/disk_cache/disk_cache.h"
@@ -26,17 +26,15 @@ class ShaderClearHelper;
// ShaderDiskCache is the interface to the on disk cache for
// GL shaders.
-//
-// While this class is both RefCounted and SupportsWeakPtr
-// when using this class you should work with the RefCounting.
-// The WeakPtr is needed interally.
class CONTENT_EXPORT ShaderDiskCache
- : public base::RefCounted<ShaderDiskCache>,
- public base::SupportsWeakPtr<ShaderDiskCache> {
+ : public base::RefCounted<ShaderDiskCache> {
public:
- void Init();
+ using ShaderLoadedCallback =
+ base::Callback<void(const std::string&, const std::string&)>;
- void set_host_id(int host_id) { host_id_ = host_id; }
+ void set_shader_loaded_callback(const ShaderLoadedCallback& callback) {
+ shader_loaded_callback_ = callback;
+ }
// Store the |shader| into the cache under |key|.
void Cache(const std::string& key, const std::string& shader);
@@ -76,32 +74,46 @@ class CONTENT_EXPORT ShaderDiskCache
explicit ShaderDiskCache(const base::FilePath& cache_path);
~ShaderDiskCache();
+ void Init(scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
void CacheCreatedCallback(int rv);
disk_cache::Backend* backend() { return backend_.get(); }
- void EntryComplete(void* entry);
+ void EntryComplete(ShaderDiskCacheEntry* entry);
void ReadComplete();
bool cache_available_;
- int host_id_;
base::FilePath cache_path_;
bool is_initialized_;
net::CompletionCallback available_callback_;
net::CompletionCallback cache_complete_callback_;
+ ShaderLoadedCallback shader_loaded_callback_;
std::unique_ptr<disk_cache::Backend> backend_;
- scoped_refptr<ShaderDiskReadHelper> helper_;
- std::map<void*, scoped_refptr<ShaderDiskCacheEntry> > entry_map_;
+ std::unique_ptr<ShaderDiskReadHelper> helper_;
+ std::unordered_map<ShaderDiskCacheEntry*,
+ std::unique_ptr<ShaderDiskCacheEntry>>
+ entries_;
DISALLOW_COPY_AND_ASSIGN(ShaderDiskCache);
};
// ShaderCacheFactory maintains a cache of ShaderDiskCache objects
// so we only create one per profile directory.
-class CONTENT_EXPORT ShaderCacheFactory {
+class CONTENT_EXPORT ShaderCacheFactory
+ : NON_EXPORTED_BASE(public base::ThreadChecker) {
public:
+ // 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.
+ static void InitInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
+
+ // Returns an instance previously created by InitInstance(). This can return
+ // nullptr if an instance has not yet been created.
static ShaderCacheFactory* GetInstance();
// Clear the shader disk cache for the given |path|. This supports unbounded
@@ -129,23 +141,28 @@ class CONTENT_EXPORT ShaderCacheFactory {
void RemoveFromCache(const base::FilePath& path);
private:
- friend struct base::DefaultSingletonTraits<ShaderCacheFactory>;
friend class ShaderClearHelper;
- ShaderCacheFactory();
+ explicit ShaderCacheFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
~ShaderCacheFactory();
+ static void CreateFactoryInstance(
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
+
+ scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner_;
+
scoped_refptr<ShaderDiskCache> GetByPath(const base::FilePath& path);
void CacheCleared(const base::FilePath& path);
- typedef std::map<base::FilePath, ShaderDiskCache*> ShaderCacheMap;
+ using ShaderCacheMap = std::map<base::FilePath, ShaderDiskCache*>;
ShaderCacheMap shader_cache_map_;
- typedef std::map<int32_t, base::FilePath> ClientIdToPathMap;
+ using ClientIdToPathMap = std::map<int32_t, base::FilePath>;
ClientIdToPathMap client_id_to_path_map_;
- typedef std::queue<scoped_refptr<ShaderClearHelper> > ShaderClearQueue;
- typedef std::map<base::FilePath, ShaderClearQueue> ShaderClearMap;
+ using ShaderClearQueue = std::queue<std::unique_ptr<ShaderClearHelper>>;
+ using ShaderClearMap = std::map<base::FilePath, ShaderClearQueue>;
ShaderClearMap shader_clear_map_;
DISALLOW_COPY_AND_ASSIGN(ShaderCacheFactory);
diff --git a/chromium/content/browser/gpu/shader_disk_cache_unittest.cc b/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
index 53951e82104..80629470a31 100644
--- a/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
+++ b/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
@@ -5,6 +5,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/gpu/shader_disk_cache.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -24,6 +25,9 @@ class ShaderDiskCacheTest : public testing::Test {
public:
ShaderDiskCacheTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ ShaderCacheFactory::InitInstance(
+ base::ThreadTaskRunnerHandle::Get(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
}
~ShaderDiskCacheTest() override {}
diff --git a/chromium/content/browser/histogram_synchronizer.cc b/chromium/content/browser/histogram_synchronizer.cc
index ad4446e0b31..ca85ad71d92 100644
--- a/chromium/content/browser/histogram_synchronizer.cc
+++ b/chromium/content/browser/histogram_synchronizer.cc
@@ -4,6 +4,8 @@
#include "content/browser/histogram_synchronizer.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/location.h"
@@ -166,7 +168,6 @@ base::LazyInstance
HistogramSynchronizer::HistogramSynchronizer()
: lock_(),
- callback_thread_(NULL),
last_used_sequence_number_(kNeverUsableSequenceNumber),
async_sequence_number_(kNeverUsableSequenceNumber) {
HistogramController::GetInstance()->Register(this);
@@ -176,7 +177,7 @@ HistogramSynchronizer::~HistogramSynchronizer() {
RequestContext::OnShutdown();
// Just in case we have any pending tasks, clear them out.
- SetCallbackTaskAndThread(NULL, base::Closure());
+ SetTaskRunnerAndCallback(nullptr, base::Closure());
}
HistogramSynchronizer* HistogramSynchronizer::GetInstance() {
@@ -205,25 +206,25 @@ void HistogramSynchronizer::FetchHistograms() {
base::TimeDelta::FromMinutes(1));
}
-void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread,
+void FetchHistogramsAsynchronously(scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback,
base::TimeDelta wait_time) {
- HistogramSynchronizer::FetchHistogramsAsynchronously(
- callback_thread, callback, wait_time);
+ HistogramSynchronizer::FetchHistogramsAsynchronously(std::move(task_runner),
+ callback, wait_time);
}
// static
void HistogramSynchronizer::FetchHistogramsAsynchronously(
- base::MessageLoop* callback_thread,
+ scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback,
base::TimeDelta wait_time) {
- DCHECK(callback_thread != NULL);
+ DCHECK(task_runner);
DCHECK(!callback.is_null());
HistogramSynchronizer* current_synchronizer =
HistogramSynchronizer::GetInstance();
- current_synchronizer->SetCallbackTaskAndThread(
- callback_thread, callback);
+ current_synchronizer->SetTaskRunnerAndCallback(std::move(task_runner),
+ callback);
current_synchronizer->RegisterAndNotifyAllProcesses(
HistogramSynchronizer::ASYNC_HISTOGRAMS, wait_time);
@@ -284,45 +285,45 @@ void HistogramSynchronizer::OnHistogramDataCollected(
request->DeleteIfAllDone();
}
-void HistogramSynchronizer::SetCallbackTaskAndThread(
- base::MessageLoop* callback_thread,
+void HistogramSynchronizer::SetTaskRunnerAndCallback(
+ scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback) {
base::Closure old_callback;
- base::MessageLoop* old_thread = NULL;
+ scoped_refptr<base::TaskRunner> old_task_runner;
{
base::AutoLock auto_lock(lock_);
old_callback = callback_;
callback_ = callback;
- old_thread = callback_thread_;
- callback_thread_ = callback_thread;
+ old_task_runner = std::move(callback_task_runner_);
+ callback_task_runner_ = std::move(task_runner);
// Prevent premature calling of our new callbacks.
async_sequence_number_ = kNeverUsableSequenceNumber;
}
// Just in case there was a task pending....
- InternalPostTask(old_thread, old_callback);
+ InternalPostTask(std::move(old_task_runner), old_callback);
}
void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
int sequence_number) {
base::Closure callback;
- base::MessageLoop* thread = NULL;
+ scoped_refptr<base::TaskRunner> task_runner;
{
base::AutoLock lock(lock_);
if (sequence_number != async_sequence_number_)
return;
callback = callback_;
- thread = callback_thread_;
+ task_runner = std::move(callback_task_runner_);
callback_.Reset();
- callback_thread_ = NULL;
}
- InternalPostTask(thread, callback);
+ InternalPostTask(std::move(task_runner), callback);
}
-void HistogramSynchronizer::InternalPostTask(base::MessageLoop* thread,
- const base::Closure& callback) {
- if (callback.is_null() || !thread)
+void HistogramSynchronizer::InternalPostTask(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::Closure& callback) {
+ if (callback.is_null() || !task_runner)
return;
- thread->task_runner()->PostTask(FROM_HERE, callback);
+ task_runner->PostTask(FROM_HERE, callback);
}
int HistogramSynchronizer::GetNextAvailableSequenceNumber(
diff --git a/chromium/content/browser/histogram_synchronizer.h b/chromium/content/browser/histogram_synchronizer.h
index 4180c24f994..2e9b79539dc 100644
--- a/chromium/content/browser/histogram_synchronizer.h
+++ b/chromium/content/browser/histogram_synchronizer.h
@@ -12,13 +12,10 @@
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
#include "base/time/time.h"
#include "content/browser/histogram_subscriber.h"
-namespace base {
-class MessageLoop;
-}
-
namespace content {
// This class maintains state that is used to upload histogram data from the
@@ -68,11 +65,12 @@ class HistogramSynchronizer : public HistogramSubscriber {
// Contact all child processes, and get them to upload to the browser any/all
// changes to histograms. When all changes have been acquired, or when the
- // wait time expires (whichever is sooner), post the callback to the
- // specified message loop. Note the callback is posted exactly once.
- static void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread,
- const base::Closure& callback,
- base::TimeDelta wait_time);
+ // wait time expires (whichever is sooner), post the callback to the specified
+ // TaskRunner. Note the callback is posted exactly once.
+ static void FetchHistogramsAsynchronously(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::Closure& callback,
+ base::TimeDelta wait_time);
private:
friend struct base::DefaultSingletonTraits<HistogramSynchronizer>;
@@ -106,18 +104,18 @@ class HistogramSynchronizer : public HistogramSubscriber {
int sequence_number,
const std::vector<std::string>& pickled_histograms) override;
- // Set the callback_thread_ and callback_ members. If these members already
- // had values, then as a side effect, post the old callback_ to the old
- // callaback_thread_. This side effect should not generally happen, but is in
- // place to assure correctness (that any tasks that were set, are eventually
- // called, and never merely discarded).
- void SetCallbackTaskAndThread(base::MessageLoop* callback_thread,
+ // Set the |callback_task_runner_| and |callback_| members. If these members
+ // already had values, then as a side effect, post the old |callback_| to the
+ // old |callback_task_runner_|. This side effect should not generally happen,
+ // but is in place to assure correctness (that any tasks that were set, are
+ // eventually called, and never merely discarded).
+ void SetTaskRunnerAndCallback(scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback);
void ForceHistogramSynchronizationDoneCallback(int sequence_number);
// Internal helper function, to post task, and record callback stats.
- void InternalPostTask(base::MessageLoop* thread,
+ void InternalPostTask(scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback);
// Gets a new sequence number to be sent to processes from browser process.
@@ -127,10 +125,10 @@ class HistogramSynchronizer : public HistogramSubscriber {
base::Lock lock_;
// When a request is made to asynchronously update the histograms, we store
- // the task and thread we use to post a completion notification in
- // callback_ and callback_thread_.
+ // the task and TaskRunner we use to post a completion notification in
+ // |callback_| and |callback_task_runner_|.
base::Closure callback_;
- base::MessageLoop* callback_thread_;
+ scoped_refptr<base::TaskRunner> callback_task_runner_;
// We don't track the actual processes that are contacted for an update, only
// the count of the number of processes, and we can sometimes time-out and
diff --git a/chromium/content/browser/host_zoom_level_context.h b/chromium/content/browser/host_zoom_level_context.h
index 3120c03267b..b1e2c5075cc 100644
--- a/chromium/content/browser/host_zoom_level_context.h
+++ b/chromium/content/browser/host_zoom_level_context.h
@@ -12,8 +12,6 @@
#include "content/browser/host_zoom_map_impl.h"
#include "content/public/browser/zoom_level_delegate.h"
-class PrefService;
-
namespace content {
struct HostZoomLevelContextDeleter;
diff --git a/chromium/content/browser/host_zoom_map_impl.h b/chromium/content/browser/host_zoom_map_impl.h
index ea323f3e15c..ad4c07e16c4 100644
--- a/chromium/content/browser/host_zoom_map_impl.h
+++ b/chromium/content/browser/host_zoom_map_impl.h
@@ -149,8 +149,6 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
// Page scale factor data for each renderer.
ViewPageScaleFactorsAreOne view_page_scale_factors_are_one_;
- // Don't expect more than a couple of tabs that are using a temporary zoom
- // level, so vector is fine for now.
TemporaryZoomLevels temporary_zoom_levels_;
// Used around accesses to |host_zoom_levels_|, |default_zoom_level_|,
diff --git a/chromium/content/browser/host_zoom_map_observer.cc b/chromium/content/browser/host_zoom_map_observer.cc
new file mode 100644
index 00000000000..90f2695a32d
--- /dev/null
+++ b/chromium/content/browser/host_zoom_map_observer.cc
@@ -0,0 +1,58 @@
+// 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/host_zoom_map_observer.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/host_zoom_map_impl.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/associated_interface_provider.h"
+
+namespace content {
+
+HostZoomMapObserver::HostZoomMapObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+HostZoomMapObserver::~HostZoomMapObserver() {}
+
+void HostZoomMapObserver::ReadyToCommitNavigation(
+ NavigationHandle* navigation_handle) {
+ if (!navigation_handle->IsInMainFrame())
+ return;
+
+ RenderFrameHost* render_frame_host =
+ navigation_handle->GetRenderFrameHost();
+ const auto& entry = host_zoom_ptrs_.find(render_frame_host);
+ if (entry == host_zoom_ptrs_.end())
+ return;
+
+ const mojom::HostZoomAssociatedPtr& host_zoom = entry->second;
+ DCHECK(host_zoom.is_bound());
+ if (host_zoom.encountered_error())
+ return;
+
+ RenderProcessHost* render_process_host = render_frame_host->GetProcess();
+ HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
+ render_process_host->GetStoragePartition()->GetHostZoomMap());
+ double zoom_level = host_zoom_map->GetZoomLevelForView(
+ navigation_handle->GetURL(), render_process_host->GetID(),
+ render_frame_host->GetRenderViewHost()->GetRoutingID());
+ host_zoom->SetHostZoomLevel(navigation_handle->GetURL(), zoom_level);
+}
+
+void HostZoomMapObserver::RenderFrameCreated(RenderFrameHost* rfh) {
+ mojom::HostZoomAssociatedPtr host_zoom;
+ rfh->GetRemoteAssociatedInterfaces()->GetInterface(&host_zoom);
+ host_zoom_ptrs_[rfh] = std::move(host_zoom);
+}
+
+void HostZoomMapObserver::RenderFrameDeleted(RenderFrameHost* rfh) {
+ const auto& entry = host_zoom_ptrs_.find(rfh);
+ DCHECK(entry != host_zoom_ptrs_.end());
+ host_zoom_ptrs_.erase(entry);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/host_zoom_map_observer.h b/chromium/content/browser/host_zoom_map_observer.h
new file mode 100644
index 00000000000..b61bad0b5f0
--- /dev/null
+++ b/chromium/content/browser/host_zoom_map_observer.h
@@ -0,0 +1,31 @@
+// 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_HOST_ZOOM_MAP_OBSERVER_H_
+#define CONTENT_BROWSER_HOST_ZOOM_MAP_OBSERVER_H_
+
+#include "content/common/host_zoom.mojom.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+class HostZoomMapObserver : private WebContentsObserver {
+ public:
+ explicit HostZoomMapObserver(WebContents* web_contents);
+ ~HostZoomMapObserver() override;
+
+ private:
+ // WebContentsObserver implementation:
+ void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override;
+ void RenderFrameCreated(RenderFrameHost* rfh) override;
+ void RenderFrameDeleted(RenderFrameHost* rfh) override;
+
+ std::map<RenderFrameHost*, mojom::HostZoomAssociatedPtr> host_zoom_ptrs_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HOST_ZOOM_MAP_OBSERVER_H_
diff --git a/chromium/content/browser/iframe_zoom_browsertest.cc b/chromium/content/browser/iframe_zoom_browsertest.cc
index 80ba2665553..857b6f71fb1 100644
--- a/chromium/content/browser/iframe_zoom_browsertest.cc
+++ b/chromium/content/browser/iframe_zoom_browsertest.cc
@@ -51,8 +51,8 @@ class IFrameZoomBrowserTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
WebContentsImpl* web_contents() {
diff --git a/chromium/content/browser/indexed_db/database_impl.cc b/chromium/content/browser/indexed_db/database_impl.cc
new file mode 100644
index 00000000000..3bd8fc8b278
--- /dev/null
+++ b/chromium/content/browser/indexed_db/database_impl.cc
@@ -0,0 +1,781 @@
+// 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/indexed_db/database_impl.h"
+
+#include "content/browser/bad_message.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
+#include "content/browser/indexed_db/indexed_db_value.h"
+#include "content/common/indexed_db/indexed_db_messages.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
+
+using std::swap;
+
+namespace content {
+
+namespace {
+const char kInvalidBlobUuid[] = "Blob UUID is invalid";
+} // namespace
+
+class DatabaseImpl::IDBThreadHelper {
+ public:
+ IDBThreadHelper(std::unique_ptr<IndexedDBConnection> connection,
+ const url::Origin& origin,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host);
+ ~IDBThreadHelper();
+
+ void CreateObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool auto_increment);
+ void DeleteObjectStore(int64_t transaction_id, int64_t object_store_id);
+ void RenameObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& new_name);
+ void CreateTransaction(int64_t transaction_id,
+ const std::vector<int64_t>& object_store_ids,
+ blink::WebIDBTransactionMode mode);
+ void Close();
+ void VersionChangeIgnored();
+ void AddObserver(int64_t transaction_id,
+ int32_t observer_id,
+ bool include_transaction,
+ bool no_records,
+ bool values,
+ uint16_t operation_types);
+ void RemoveObservers(const std::vector<int32_t>& observers);
+ void Get(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void GetAll(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ int64_t max_count,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void Put(int64_t transaction_id,
+ int64_t object_store_id,
+ ::indexed_db::mojom::ValuePtr value,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> handles,
+ const IndexedDBKey& key,
+ blink::WebIDBPutMode mode,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void SetIndexKeys(int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKey& primary_key,
+ const std::vector<IndexedDBIndexKeys>& index_keys);
+ void SetIndexesReady(int64_t transaction_id,
+ int64_t object_store_id,
+ const std::vector<int64_t>& index_ids);
+ void OpenCursor(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection direction,
+ bool key_only,
+ blink::WebIDBTaskType task_type,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void Count(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void DeleteRange(int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKeyRange& key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void Clear(int64_t transaction_id,
+ int64_t object_store_id,
+ scoped_refptr<IndexedDBCallbacks> callbacks);
+ void CreateIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry);
+ void DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id);
+ void RenameIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& new_name);
+ void Abort(int64_t transaction_id);
+ void Commit(int64_t transaction_id);
+ void OnGotUsageAndQuotaForCommit(int64_t transaction_id,
+ storage::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota);
+ void AckReceivedBlobs(const std::vector<std::string>& uuids);
+
+ private:
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_;
+ std::unique_ptr<IndexedDBConnection> connection_;
+ const url::Origin origin_;
+ base::WeakPtrFactory<IDBThreadHelper> weak_factory_;
+};
+
+DatabaseImpl::DatabaseImpl(
+ std::unique_ptr<IndexedDBConnection> connection,
+ const url::Origin& origin,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host)
+ : dispatcher_host_(dispatcher_host),
+ origin_(origin),
+ idb_runner_(base::ThreadTaskRunnerHandle::Get()) {
+ helper_ = new IDBThreadHelper(std::move(connection), origin,
+ std::move(dispatcher_host));
+}
+
+DatabaseImpl::~DatabaseImpl() {
+ idb_runner_->DeleteSoon(FROM_HERE, helper_);
+}
+
+void DatabaseImpl::CreateObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool auto_increment) {
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::CreateObjectStore,
+ base::Unretained(helper_), transaction_id,
+ object_store_id, name, key_path, auto_increment));
+}
+
+void DatabaseImpl::DeleteObjectStore(int64_t transaction_id,
+ int64_t object_store_id) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::DeleteObjectStore, base::Unretained(helper_),
+ transaction_id, object_store_id));
+}
+
+void DatabaseImpl::RenameObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& new_name) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::RenameObjectStore, base::Unretained(helper_),
+ transaction_id, object_store_id, new_name));
+}
+
+void DatabaseImpl::CreateTransaction(
+ int64_t transaction_id,
+ const std::vector<int64_t>& object_store_ids,
+ blink::WebIDBTransactionMode mode) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::CreateTransaction, base::Unretained(helper_),
+ transaction_id, object_store_ids, mode));
+}
+
+void DatabaseImpl::Close() {
+ idb_runner_->PostTask(FROM_HERE, base::Bind(&IDBThreadHelper::Close,
+ base::Unretained(helper_)));
+}
+
+void DatabaseImpl::VersionChangeIgnored() {
+ idb_runner_->PostTask(FROM_HERE,
+ base::Bind(&IDBThreadHelper::VersionChangeIgnored,
+ base::Unretained(helper_)));
+}
+
+void DatabaseImpl::AddObserver(int64_t transaction_id,
+ int32_t observer_id,
+ bool include_transaction,
+ bool no_records,
+ bool values,
+ uint16_t operation_types) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::AddObserver, base::Unretained(helper_),
+ transaction_id, observer_id, include_transaction, no_records,
+ values, operation_types));
+}
+
+void DatabaseImpl::RemoveObservers(const std::vector<int32_t>& observers) {
+ idb_runner_->PostTask(FROM_HERE,
+ base::Bind(&IDBThreadHelper::RemoveObservers,
+ base::Unretained(helper_), observers));
+}
+
+void DatabaseImpl::Get(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::Get, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id,
+ key_range, key_only, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::GetAll(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ int64_t max_count,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::GetAll, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id, key_range, key_only,
+ max_count, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::Put(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ ::indexed_db::mojom::ValuePtr value,
+ const IndexedDBKey& key,
+ blink::WebIDBPutMode mode,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
+ for (const auto& info : value->blob_or_file_info) {
+ std::unique_ptr<storage::BlobDataHandle> handle =
+ dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID(
+ info->uuid);
+ if (!handle) {
+ mojo::ReportBadMessage(kInvalidBlobUuid);
+ return;
+ }
+ handles.push_back(std::move(handle));
+ }
+
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_),
+ transaction_id, object_store_id,
+ base::Passed(&value), base::Passed(&handles), key,
+ mode, index_keys, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::SetIndexKeys(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKey& primary_key,
+ const std::vector<IndexedDBIndexKeys>& index_keys) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::SetIndexKeys, base::Unretained(helper_),
+ transaction_id, object_store_id, primary_key, index_keys));
+}
+
+void DatabaseImpl::SetIndexesReady(int64_t transaction_id,
+ int64_t object_store_id,
+ const std::vector<int64_t>& index_ids) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::SetIndexesReady, base::Unretained(helper_),
+ transaction_id, object_store_id, index_ids));
+}
+
+void DatabaseImpl::OpenCursor(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection direction,
+ bool key_only,
+ blink::WebIDBTaskType task_type,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::OpenCursor, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id, key_range,
+ direction, key_only, task_type, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::Count(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::Count, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id,
+ key_range, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::DeleteRange(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKeyRange& key_range,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::DeleteRange, base::Unretained(helper_),
+ transaction_id, object_store_id, key_range,
+ base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::Clear(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
+ dispatcher_host_.get(), origin_, std::move(callbacks_info)));
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::Clear, base::Unretained(helper_),
+ transaction_id, object_store_id, base::Passed(&callbacks)));
+}
+
+void DatabaseImpl::CreateIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::CreateIndex, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id, name, key_path,
+ unique, multi_entry));
+}
+
+void DatabaseImpl::DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::DeleteIndex, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id));
+}
+
+void DatabaseImpl::RenameIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& new_name) {
+ idb_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IDBThreadHelper::RenameIndex, base::Unretained(helper_),
+ transaction_id, object_store_id, index_id, new_name));
+}
+
+void DatabaseImpl::Abort(int64_t transaction_id) {
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::Abort, base::Unretained(helper_),
+ transaction_id));
+}
+
+void DatabaseImpl::Commit(int64_t transaction_id) {
+ idb_runner_->PostTask(
+ FROM_HERE, base::Bind(&IDBThreadHelper::Commit, base::Unretained(helper_),
+ transaction_id));
+}
+
+void DatabaseImpl::AckReceivedBlobs(const std::vector<std::string>& uuids) {
+ for (const auto& uuid : uuids)
+ dispatcher_host_->DropBlobData(uuid);
+}
+
+DatabaseImpl::IDBThreadHelper::IDBThreadHelper(
+ std::unique_ptr<IndexedDBConnection> connection,
+ const url::Origin& origin,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host)
+ : dispatcher_host_(std::move(dispatcher_host)),
+ connection_(std::move(connection)),
+ origin_(origin),
+ weak_factory_(this) {
+ dispatcher_host_->context()->ConnectionOpened(origin_, connection.get());
+}
+
+DatabaseImpl::IDBThreadHelper::~IDBThreadHelper() {
+ if (connection_->IsConnected())
+ connection_->Close();
+ dispatcher_host_->context()->ConnectionClosed(origin_, connection_.get());
+}
+
+void DatabaseImpl::IDBThreadHelper::CreateObjectStore(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool auto_increment) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->CreateObjectStore(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ name, key_path, auto_increment);
+}
+
+void DatabaseImpl::IDBThreadHelper::DeleteObjectStore(int64_t transaction_id,
+ int64_t object_store_id) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->DeleteObjectStore(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id);
+}
+
+void DatabaseImpl::IDBThreadHelper::RenameObjectStore(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& new_name) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->RenameObjectStore(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ new_name);
+}
+
+void DatabaseImpl::IDBThreadHelper::CreateTransaction(
+ int64_t transaction_id,
+ const std::vector<int64_t>& object_store_ids,
+ blink::WebIDBTransactionMode mode) {
+ if (!connection_->IsConnected())
+ return;
+
+ int64_t host_transaction_id =
+ dispatcher_host_->HostTransactionId(transaction_id);
+ if (!dispatcher_host_->RegisterTransactionId(host_transaction_id, origin_)) {
+ DLOG(ERROR) << "Duplicate host_transaction_id.";
+ return;
+ }
+
+ connection_->database()->CreateTransaction(
+ host_transaction_id, connection_.get(), object_store_ids, mode);
+}
+
+void DatabaseImpl::IDBThreadHelper::Close() {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->Close();
+}
+
+void DatabaseImpl::IDBThreadHelper::VersionChangeIgnored() {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->VersionChangeIgnored();
+}
+
+void DatabaseImpl::IDBThreadHelper::AddObserver(int64_t transaction_id,
+ int32_t observer_id,
+ bool include_transaction,
+ bool no_records,
+ bool values,
+ uint16_t operation_types) {
+ if (!connection_->IsConnected())
+ return;
+
+ IndexedDBObserver::Options options(include_transaction, no_records, values,
+ operation_types);
+ connection_->database()->AddPendingObserver(
+ dispatcher_host_->HostTransactionId(transaction_id), observer_id,
+ options);
+}
+
+void DatabaseImpl::IDBThreadHelper::RemoveObservers(
+ const std::vector<int32_t>& observers) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->RemoveObservers(observers);
+}
+
+void DatabaseImpl::IDBThreadHelper::Get(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->Get(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, base::MakeUnique<IndexedDBKeyRange>(key_range), key_only,
+ callbacks);
+}
+
+void DatabaseImpl::IDBThreadHelper::GetAll(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ int64_t max_count,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->GetAll(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, base::MakeUnique<IndexedDBKeyRange>(key_range), key_only,
+ max_count, std::move(callbacks));
+}
+
+void DatabaseImpl::IDBThreadHelper::Put(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ ::indexed_db::mojom::ValuePtr mojo_value,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> handles,
+ const IndexedDBKey& key,
+ blink::WebIDBPutMode mode,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ int64_t host_transaction_id =
+ dispatcher_host_->HostTransactionId(transaction_id);
+
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ std::vector<IndexedDBBlobInfo> blob_info(
+ mojo_value->blob_or_file_info.size());
+ for (size_t i = 0; i < mojo_value->blob_or_file_info.size(); ++i) {
+ const auto& info = mojo_value->blob_or_file_info[i];
+ if (info->file) {
+ if (!info->file->path.empty()) {
+ if (!policy->CanReadFile(dispatcher_host_->ipc_process_id(),
+ info->file->path)) {
+ bad_message::ReceivedBadMessage(dispatcher_host_.get(),
+ bad_message::IDBDH_CAN_READ_FILE);
+ return;
+ }
+ }
+ blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path,
+ info->file->name, info->mime_type);
+ if (info->size != static_cast<uint64_t>(-1)) {
+ blob_info[i].set_last_modified(info->file->last_modified);
+ blob_info[i].set_size(info->size);
+ }
+ } else {
+ blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size);
+ }
+ }
+
+ uint64_t commit_size = mojo_value->bits.size();
+ IndexedDBValue value;
+ swap(value.bits, mojo_value->bits);
+ swap(value.blob_info, blob_info);
+ connection_->database()->Put(host_transaction_id, object_store_id, &value,
+ &handles, base::MakeUnique<IndexedDBKey>(key),
+ mode, std::move(callbacks), index_keys);
+
+ // Size can't be big enough to overflow because it represents the
+ // actual bytes passed through IPC.
+ dispatcher_host_->AddToTransaction(host_transaction_id, commit_size);
+}
+
+void DatabaseImpl::IDBThreadHelper::SetIndexKeys(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKey& primary_key,
+ const std::vector<IndexedDBIndexKeys>& index_keys) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->SetIndexKeys(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ base::MakeUnique<IndexedDBKey>(primary_key), index_keys);
+}
+
+void DatabaseImpl::IDBThreadHelper::SetIndexesReady(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const std::vector<int64_t>& index_ids) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->SetIndexesReady(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_ids);
+}
+
+void DatabaseImpl::IDBThreadHelper::OpenCursor(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection direction,
+ bool key_only,
+ blink::WebIDBTaskType task_type,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->OpenCursor(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, base::MakeUnique<IndexedDBKeyRange>(key_range), direction,
+ key_only, task_type, std::move(callbacks));
+}
+
+void DatabaseImpl::IDBThreadHelper::Count(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->Count(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, base::MakeUnique<IndexedDBKeyRange>(key_range),
+ std::move(callbacks));
+}
+
+void DatabaseImpl::IDBThreadHelper::DeleteRange(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKeyRange& key_range,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->DeleteRange(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ base::MakeUnique<IndexedDBKeyRange>(key_range), std::move(callbacks));
+}
+
+void DatabaseImpl::IDBThreadHelper::Clear(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ scoped_refptr<IndexedDBCallbacks> callbacks) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->Clear(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ callbacks);
+}
+
+void DatabaseImpl::IDBThreadHelper::CreateIndex(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->CreateIndex(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, name, key_path, unique, multi_entry);
+}
+
+void DatabaseImpl::IDBThreadHelper::DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->DeleteIndex(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id);
+}
+
+void DatabaseImpl::IDBThreadHelper::RenameIndex(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& new_name) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->RenameIndex(
+ dispatcher_host_->HostTransactionId(transaction_id), object_store_id,
+ index_id, new_name);
+}
+
+void DatabaseImpl::IDBThreadHelper::Abort(int64_t transaction_id) {
+ if (!connection_->IsConnected())
+ return;
+
+ connection_->database()->Abort(
+ dispatcher_host_->HostTransactionId(transaction_id));
+}
+
+void DatabaseImpl::IDBThreadHelper::Commit(int64_t transaction_id) {
+ if (!connection_->IsConnected())
+ return;
+
+ int64_t host_transaction_id =
+ dispatcher_host_->HostTransactionId(transaction_id);
+ // May have been aborted by back end before front-end could request commit.
+ int64_t transaction_size;
+ if (!dispatcher_host_->GetTransactionSize(host_transaction_id,
+ &transaction_size))
+ return;
+
+ // Always allow empty or delete-only transactions.
+ if (transaction_size == 0) {
+ connection_->database()->Commit(host_transaction_id);
+ return;
+ }
+
+ dispatcher_host_->context()->quota_manager_proxy()->GetUsageAndQuota(
+ dispatcher_host_->context()->TaskRunner(), origin_.GetURL(),
+ storage::kStorageTypeTemporary,
+ base::Bind(&IDBThreadHelper::OnGotUsageAndQuotaForCommit,
+ weak_factory_.GetWeakPtr(), transaction_id));
+}
+
+void DatabaseImpl::IDBThreadHelper::OnGotUsageAndQuotaForCommit(
+ int64_t transaction_id,
+ storage::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota) {
+ // May have disconnected while quota check was pending.
+ if (!connection_->IsConnected())
+ return;
+
+ int64_t host_transaction_id =
+ dispatcher_host_->HostTransactionId(transaction_id);
+ // May have aborted while quota check was pending.
+ int64_t transaction_size;
+ if (!dispatcher_host_->GetTransactionSize(host_transaction_id,
+ &transaction_size))
+ return;
+
+ if (status == storage::kQuotaStatusOk && usage + transaction_size <= quota) {
+ connection_->database()->Commit(host_transaction_id);
+ } else {
+ connection_->database()->Abort(
+ host_transaction_id,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/database_impl.h b/chromium/content/browser/indexed_db/database_impl.h
new file mode 100644
index 00000000000..bb5e9f0fb71
--- /dev/null
+++ b/chromium/content/browser/indexed_db/database_impl.h
@@ -0,0 +1,130 @@
+// 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_INDEXED_DB_DATABASE_IMPL_H_
+#define CONTENT_BROWSER_INDEXED_DB_DATABASE_IMPL_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/indexed_db/indexed_db.mojom.h"
+
+namespace content {
+
+class IndexedDBConnection;
+class IndexedDBDispatcherHost;
+
+class DatabaseImpl : public ::indexed_db::mojom::Database {
+ public:
+ explicit DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,
+ const url::Origin& origin,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host);
+ ~DatabaseImpl() override;
+
+ // ::indexed_db::mojom::Database implementation
+ void CreateObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool auto_increment) override;
+ void DeleteObjectStore(int64_t transaction_id,
+ int64_t object_store_id) override;
+ void RenameObjectStore(int64_t transaction_id,
+ int64_t object_store_id,
+ const base::string16& new_name) override;
+ void CreateTransaction(int64_t transaction_id,
+ const std::vector<int64_t>& object_store_ids,
+ blink::WebIDBTransactionMode mode) override;
+ void Close() override;
+ void VersionChangeIgnored() override;
+ void AddObserver(int64_t transaction_id,
+ int32_t observer_id,
+ bool include_transaction,
+ bool no_records,
+ bool values,
+ uint16_t operation_types) override;
+ void RemoveObservers(const std::vector<int32_t>& observers) override;
+ void Get(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void GetAll(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ int64_t max_count,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void Put(int64_t transaction_id,
+ int64_t object_store_id,
+ indexed_db::mojom::ValuePtr value,
+ const IndexedDBKey& key,
+ blink::WebIDBPutMode mode,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void SetIndexKeys(int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKey& primary_key,
+ const std::vector<IndexedDBIndexKeys>& index_keys) override;
+ void SetIndexesReady(int64_t transaction_id,
+ int64_t object_store_id,
+ const std::vector<int64_t>& index_ids) override;
+ void OpenCursor(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection direction,
+ bool key_only,
+ blink::WebIDBTaskType task_type,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) override;
+ void Count(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKeyRange& key_range,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void DeleteRange(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ const IndexedDBKeyRange& key_range,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void Clear(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override;
+ void CreateIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& name,
+ const IndexedDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry) override;
+ void DeleteIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id) override;
+ void RenameIndex(int64_t transaction_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const base::string16& new_name) override;
+ void Abort(int64_t transaction_id) override;
+ void Commit(int64_t transaction_id) override;
+ void AckReceivedBlobs(const std::vector<std::string>& uuids) override;
+
+ private:
+ class IDBThreadHelper;
+
+ IDBThreadHelper* helper_;
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_;
+ const url::Origin origin_;
+ scoped_refptr<base::SingleThreadTaskRunner> idb_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DatabaseImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_DATABASE_IMPL_H_
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 5b90e6834c7..e0945891378 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -27,7 +27,6 @@
#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_leveldb_coding.h"
-#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
@@ -89,7 +88,7 @@ bool MakeIDBBlobDirectory(const FilePath& path_base,
}
static std::string ComputeOriginIdentifier(const Origin& origin) {
- return storage::GetIdentifierFromOrigin(GURL(origin.Serialize())) + "@1";
+ return storage::GetIdentifierFromOrigin(origin.GetURL()) + "@1";
}
static FilePath ComputeCorruptionFileName(const Origin& origin) {
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 b26c323d006..48c46c060a9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -26,13 +26,13 @@
#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_metadata.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"
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 8783d3b1049..1c16bd0b058 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -14,32 +14,113 @@
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/fileapi_message_filter.h"
+#include "content/browser/indexed_db/database_impl.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
-#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/indexed_db_return_value.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_messages.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/shareable_file_reference.h"
#include "storage/browser/quota/quota_manager.h"
+using indexed_db::mojom::CallbacksAssociatedPtrInfo;
+using std::swap;
using storage::ShareableFileReference;
namespace content {
namespace {
const int32_t kNoCursor = -1;
-const int32_t kNoDatabaseCallbacks = -1;
const int64_t kNoTransaction = -1;
+
+void ConvertBlobInfo(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
+ blob_or_file_info->reserve(blob_info.size());
+ for (const auto& iter : blob_info) {
+ if (!iter.mark_used_callback().is_null())
+ iter.mark_used_callback().Run();
+
+ auto info = ::indexed_db::mojom::BlobInfo::New();
+ info->mime_type = iter.type();
+ info->size = iter.size();
+ if (iter.is_file()) {
+ info->file = ::indexed_db::mojom::FileInfo::New();
+ info->file->name = iter.file_name();
+ info->file->path = iter.file_path();
+ info->file->last_modified = iter.last_modified();
+ }
+ blob_or_file_info->push_back(std::move(info));
+ }
+}
+
+// Destructively converts an IndexedDBReturnValue to a Mojo ReturnValue.
+::indexed_db::mojom::ReturnValuePtr ConvertReturnValue(
+ IndexedDBReturnValue* value) {
+ auto mojo_value = ::indexed_db::mojom::ReturnValue::New();
+ mojo_value->value = ::indexed_db::mojom::Value::New();
+ if (value->primary_key.IsValid()) {
+ mojo_value->primary_key = value->primary_key;
+ mojo_value->key_path = value->key_path;
+ }
+ if (!value->empty())
+ swap(mojo_value->value->bits, value->bits);
+ ConvertBlobInfo(value->blob_info, &mojo_value->value->blob_or_file_info);
+ return mojo_value;
}
+} // namespace
+
+class IndexedDBCallbacks::IOThreadHelper {
+ public:
+ IOThreadHelper(CallbacksAssociatedPtrInfo callbacks_info,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host);
+ ~IOThreadHelper();
+
+ void SendError(const IndexedDBDatabaseError& error);
+ void SendSuccessStringList(const std::vector<base::string16>& value);
+ void SendBlocked(int64_t existing_version);
+ void SendUpgradeNeeded(std::unique_ptr<DatabaseImpl> database,
+ int64_t old_version,
+ blink::WebIDBDataLoss data_loss,
+ const std::string& data_loss_message,
+ const content::IndexedDBDatabaseMetadata& metadata);
+ void SendSuccessDatabase(std::unique_ptr<DatabaseImpl> database,
+ const content::IndexedDBDatabaseMetadata& metadata);
+ void SendSuccessCursor(int32_t cursor_id,
+ const IndexedDBKey& key,
+ const IndexedDBKey& primary_key,
+ ::indexed_db::mojom::ValuePtr value,
+ const std::vector<IndexedDBBlobInfo>& blob_info);
+ void SendSuccessValue(::indexed_db::mojom::ReturnValuePtr value,
+ const std::vector<IndexedDBBlobInfo>& blob_info);
+ void SendSuccessArray(
+ std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values,
+ const std::vector<IndexedDBReturnValue>& values);
+ void SendSuccessKey(const IndexedDBKey& value);
+ void SendSuccessInteger(int64_t value);
+ void SendSuccess();
+
+ std::string CreateBlobData(const IndexedDBBlobInfo& blob_info);
+ bool CreateAllBlobs(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info);
+
+ private:
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_;
+ ::indexed_db::mojom::CallbacksAssociatedPtr callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
+};
+
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32_t ipc_thread_id,
int32_t ipc_callbacks_id)
@@ -48,10 +129,9 @@ IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(kNoCursor),
host_transaction_id_(kNoTransaction),
- ipc_database_id_(kNoDatabase),
- ipc_database_callbacks_id_(kNoDatabaseCallbacks),
data_loss_(blink::WebIDBDataLossNone),
- sent_blocked_(false) {}
+ sent_blocked_(false),
+ io_helper_(nullptr) {}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32_t ipc_thread_id,
@@ -62,36 +142,44 @@ IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(ipc_cursor_id),
host_transaction_id_(kNoTransaction),
- ipc_database_id_(kNoDatabase),
- ipc_database_callbacks_id_(kNoDatabaseCallbacks),
data_loss_(blink::WebIDBDataLossNone),
- sent_blocked_(false) {}
+ sent_blocked_(false),
+ io_helper_(nullptr) {}
-IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
- int32_t ipc_thread_id,
- int32_t ipc_callbacks_id,
- int32_t ipc_database_callbacks_id,
- int64_t host_transaction_id,
- const url::Origin& origin)
+IndexedDBCallbacks::IndexedDBCallbacks(
+ IndexedDBDispatcherHost* dispatcher_host,
+ const url::Origin& origin,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info)
: dispatcher_host_(dispatcher_host),
- ipc_callbacks_id_(ipc_callbacks_id),
- ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(kNoCursor),
- host_transaction_id_(host_transaction_id),
+ host_transaction_id_(kNoTransaction),
origin_(origin),
- ipc_database_id_(kNoDatabase),
- ipc_database_callbacks_id_(ipc_database_callbacks_id),
data_loss_(blink::WebIDBDataLossNone),
- sent_blocked_(false) {}
+ sent_blocked_(false),
+ io_helper_(
+ new IOThreadHelper(std::move(callbacks_info), dispatcher_host_)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ thread_checker_.DetachFromThread();
+}
-IndexedDBCallbacks::~IndexedDBCallbacks() {}
+IndexedDBCallbacks::~IndexedDBCallbacks() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
- ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
- dispatcher_host_ = NULL;
+ if (io_helper_) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendError,
+ base::Unretained(io_helper_.get()), error));
+ } else {
+ dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
+ ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
+ }
+ dispatcher_host_ = nullptr;
if (!connection_open_start_time_.is_null()) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -102,38 +190,34 @@ void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
}
void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
- DCHECK(dispatcher_host_.get());
-
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
- DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
-
- std::vector<base::string16> list;
- for (unsigned i = 0; i < value.size(); ++i)
- list.push_back(value[i]);
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
- ipc_thread_id_, ipc_callbacks_id_, list));
- dispatcher_host_ = NULL;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessStringList,
+ base::Unretained(io_helper_.get()), value));
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnBlocked(int64_t existing_version) {
- DCHECK(dispatcher_host_.get());
-
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
- // No transaction/db callbacks for DeleteDatabase.
- DCHECK_EQ(kNoTransaction == host_transaction_id_,
- kNoDatabaseCallbacks == ipc_database_callbacks_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
if (sent_blocked_)
return;
sent_blocked_ = true;
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
- ipc_thread_id_, ipc_callbacks_id_, existing_version));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendBlocked,
+ base::Unretained(io_helper_.get()), existing_version));
if (!connection_open_start_time_.is_null()) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -148,30 +232,26 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
std::unique_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata,
const IndexedDBDataLossInfo& data_loss_info) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
- DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_NE(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
+ DCHECK_EQ(kNoCursor, ipc_cursor_id_);
+ DCHECK(!database_sent_);
data_loss_ = data_loss_info.status;
dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_);
- int32_t ipc_database_id =
- dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_);
- if (ipc_database_id < 0)
- return;
- ipc_database_id_ = ipc_database_id;
- IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
- params.ipc_thread_id = ipc_thread_id_;
- params.ipc_callbacks_id = ipc_callbacks_id_;
- params.ipc_database_id = ipc_database_id;
- params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
- params.old_version = old_version;
- params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
- params.data_loss = data_loss_info.status;
- params.data_loss_message = data_loss_info.message;
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
+ database_sent_ = true;
+ auto database = base::MakeUnique<DatabaseImpl>(std::move(connection), origin_,
+ dispatcher_host_);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendUpgradeNeeded,
+ base::Unretained(io_helper_.get()), base::Passed(&database),
+ old_version, data_loss_info.status, data_loss_info.message,
+ metadata));
if (!connection_open_start_time_.is_null()) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -184,29 +264,28 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
void IndexedDBCallbacks::OnSuccess(
std::unique_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_NE(kNoTransaction, host_transaction_id_);
- DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
- DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
+ DCHECK_EQ(database_sent_, !connection);
scoped_refptr<IndexedDBCallbacks> self(this);
- int32_t ipc_object_id = kNoDatabase;
- // Only register if the connection was not previously sent in OnUpgradeNeeded.
- if (ipc_database_id_ == kNoDatabase) {
- ipc_object_id =
- dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_);
- }
+ // Only send a new Database if the connection was not previously sent in
+ // OnUpgradeNeeded.
+ std::unique_ptr<DatabaseImpl> database;
+ if (!database_sent_)
+ database.reset(
+ new DatabaseImpl(std::move(connection), origin_, dispatcher_host_));
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
- ipc_thread_id_,
- ipc_callbacks_id_,
- ipc_database_callbacks_id_,
- ipc_object_id,
- IndexedDBDispatcherHost::ConvertMetadata(metadata)));
- dispatcher_host_ = NULL;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessDatabase,
+ base::Unretained(io_helper_.get()),
+ base::Passed(&database), metadata));
+ dispatcher_host_ = nullptr;
if (!connection_open_start_time_.is_null()) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -282,22 +361,6 @@ static void BlobLookupForCursorPrefetch(
new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
}
-static void BlobLookupForGetAll(
- IndexedDBMsg_CallbacksSuccessArray_Params* params,
- scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
- const std::vector<IndexedDBReturnValue>& values) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_EQ(values.size(), params->values.size());
-
- for (size_t i = 0; i < values.size(); ++i) {
- if (!CreateAllBlobs(values[i].blob_info,
- &params->values[i].blob_or_file_info, dispatcher_host))
- return;
- }
-
- dispatcher_host->Send(new IndexedDBMsg_CallbacksSuccessArray(*params));
-}
-
static void FillInBlobData(
const std::vector<IndexedDBBlobInfo>& blob_info,
std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
@@ -335,51 +398,42 @@ void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
IndexedDBValue* value) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- int32_t ipc_object_id = dispatcher_host_->Add(cursor.get());
- std::unique_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
- new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
- params->ipc_thread_id = ipc_thread_id_;
- params->ipc_callbacks_id = ipc_callbacks_id_;
- params->ipc_cursor_id = ipc_object_id;
- params->key = key;
- params->primary_key = primary_key;
- if (value && !value->empty())
- std::swap(params->value.bits, value->bits);
- // TODO(alecflett): Avoid a copy here: the whole params object is
- // being copied into the message.
- if (!value || value->blob_info.empty()) {
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
- } else {
- IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
- FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
- RegisterBlobsAndSend(
- value->blob_info,
- base::Bind(
- CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
- IndexedDBMsg_CallbacksSuccessIDBCursor>,
- base::Owned(params.release()), dispatcher_host_, value->blob_info,
- base::Unretained(&p->value.blob_or_file_info)));
+ ::indexed_db::mojom::ValuePtr mojo_value;
+ std::vector<IndexedDBBlobInfo> blob_info;
+ if (value) {
+ mojo_value = ::indexed_db::mojom::Value::New();
+ if (!value->empty())
+ swap(mojo_value->bits, value->bits);
+ ConvertBlobInfo(value->blob_info, &mojo_value->blob_or_file_info);
+ blob_info = value->blob_info;
}
- dispatcher_host_ = NULL;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessCursor,
+ base::Unretained(io_helper_.get()),
+ dispatcher_host_->Add(cursor.get()), key, primary_key,
+ base::Passed(&mojo_value), base::Passed(&blob_info)));
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
const IndexedDBKey& primary_key,
IndexedDBValue* value) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(!io_helper_);
DCHECK_NE(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
IndexedDBCursor* idb_cursor =
@@ -397,7 +451,7 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
params->key = key;
params->primary_key = primary_key;
if (value && !value->empty())
- std::swap(params->value.bits, value->bits);
+ swap(params->value.bits, value->bits);
// TODO(alecflett): Avoid a copy here: the whole params object is
// being copied into the message.
if (!value || value->blob_info.empty()) {
@@ -415,22 +469,21 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
value->blob_info,
base::Unretained(&p->value.blob_or_file_info)));
}
- dispatcher_host_ = NULL;
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccessWithPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
std::vector<IndexedDBValue>* values) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(!io_helper_);
DCHECK_EQ(keys.size(), primary_keys.size());
DCHECK_EQ(keys.size(), values->size());
- DCHECK(dispatcher_host_.get());
-
DCHECK_NE(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
std::vector<IndexedDBKey> msg_keys;
@@ -475,11 +528,12 @@ void IndexedDBCallbacks::OnSuccessWithPrefetch(
dispatcher_host_->Send(
new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
}
- dispatcher_host_ = NULL;
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
if (value && value->primary_key.IsValid()) {
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
@@ -487,121 +541,119 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
}
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- std::unique_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
- new IndexedDBMsg_CallbacksSuccessValue_Params());
- params->ipc_thread_id = ipc_thread_id_;
- params->ipc_callbacks_id = ipc_callbacks_id_;
- if (value && value->primary_key.IsValid()) {
- params->value.primary_key = value->primary_key;
- params->value.key_path = value->key_path;
- }
- if (value && !value->empty())
- std::swap(params->value.bits, value->bits);
- if (!value || value->blob_info.empty()) {
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
+ if (io_helper_) {
+ DCHECK_EQ(kNoCursor, ipc_cursor_id_);
+
+ ::indexed_db::mojom::ReturnValuePtr mojo_value;
+ std::vector<IndexedDBBlobInfo> blob_info;
+ if (value) {
+ mojo_value = ConvertReturnValue(value);
+ blob_info = value->blob_info;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessValue,
+ base::Unretained(io_helper_.get()),
+ base::Passed(&mojo_value), base::Passed(&blob_info)));
} else {
- IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
- FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
- RegisterBlobsAndSend(
- value->blob_info,
- base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
- IndexedDBMsg_CallbacksSuccessValue>,
- base::Owned(params.release()), dispatcher_host_,
- value->blob_info,
- base::Unretained(&p->value.blob_or_file_info)));
+ auto params = base::MakeUnique<IndexedDBMsg_CallbacksSuccessValue_Params>();
+ params->ipc_thread_id = ipc_thread_id_;
+ params->ipc_callbacks_id = ipc_callbacks_id_;
+ if (value && value->primary_key.IsValid()) {
+ params->value.primary_key = value->primary_key;
+ params->value.key_path = value->key_path;
+ }
+ if (value && !value->empty())
+ swap(params->value.bits, value->bits);
+ if (!value || value->blob_info.empty()) {
+ dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
+ } else {
+ IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
+ FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
+ RegisterBlobsAndSend(
+ value->blob_info,
+ base::Bind(
+ CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
+ IndexedDBMsg_CallbacksSuccessValue>,
+ base::Owned(params.release()), dispatcher_host_, value->blob_info,
+ base::Unretained(&p->value.blob_or_file_info)));
+ }
}
- dispatcher_host_ = NULL;
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccessArray(
- std::vector<IndexedDBReturnValue>* values,
- const IndexedDBKeyPath& key_path) {
- DCHECK(dispatcher_host_.get());
+ std::vector<IndexedDBReturnValue>* values) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+ DCHECK_EQ(kNoCursor, ipc_cursor_id_);
- std::unique_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params(
- new IndexedDBMsg_CallbacksSuccessArray_Params());
- params->ipc_thread_id = ipc_thread_id_;
- params->ipc_callbacks_id = ipc_callbacks_id_;
- params->values.resize(values->size());
-
- bool found_blob_info = false;
- for (size_t i = 0; i < values->size(); ++i) {
- IndexedDBMsg_ReturnValue& pvalue = params->values[i];
- IndexedDBReturnValue& value = (*values)[i];
- pvalue.bits.swap(value.bits);
- if (!value.blob_info.empty()) {
- found_blob_info = true;
- FillInBlobData(value.blob_info, &pvalue.blob_or_file_info);
- for (const auto& blob_info : value.blob_info) {
- if (!blob_info.mark_used_callback().is_null())
- blob_info.mark_used_callback().Run();
- }
- }
- pvalue.primary_key = value.primary_key;
- pvalue.key_path = key_path;
- }
+ std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values;
+ mojo_values.reserve(values->size());
+ for (size_t i = 0; i < values->size(); ++i)
+ mojo_values.push_back(ConvertReturnValue(&(*values)[i]));
- if (found_blob_info) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(BlobLookupForGetAll, base::Owned(params.release()),
- dispatcher_host_, *values));
- } else {
- dispatcher_host_->Send(
- new IndexedDBMsg_CallbacksSuccessArray(*params.get()));
- }
- dispatcher_host_ = NULL;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessArray,
+ base::Unretained(io_helper_.get()),
+ base::Passed(&mojo_values), *values));
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
- ipc_thread_id_, ipc_callbacks_id_, value));
- dispatcher_host_ = NULL;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessKey,
+ base::Unretained(io_helper_.get()), value));
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccess(int64_t value) {
- DCHECK(dispatcher_host_.get());
-
- DCHECK_EQ(kNoCursor, ipc_cursor_id_);
- DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
- DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ if (io_helper_) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccessInteger,
+ base::Unretained(io_helper_.get()), value));
+ } else {
+ DCHECK_EQ(kNoCursor, ipc_cursor_id_);
+ DCHECK_EQ(kNoTransaction, host_transaction_id_);
+ DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
- ipc_thread_id_, ipc_callbacks_id_, value));
- dispatcher_host_ = NULL;
+ dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
+ ipc_thread_id_, ipc_callbacks_id_, value));
+ }
+ dispatcher_host_ = nullptr;
}
void IndexedDBCallbacks::OnSuccess() {
- DCHECK(dispatcher_host_.get());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(dispatcher_host_);
+ DCHECK(io_helper_);
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
- DCHECK_EQ(kNoDatabase, ipc_database_id_);
- DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
- dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
- ipc_thread_id_, ipc_callbacks_id_));
- dispatcher_host_ = NULL;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendSuccess,
+ base::Unretained(io_helper_.get())));
+ dispatcher_host_ = nullptr;
}
bool IndexedDBCallbacks::IsValid() const {
@@ -615,4 +667,130 @@ void IndexedDBCallbacks::SetConnectionOpenStartTime(
connection_open_start_time_ = start_time;
}
+IndexedDBCallbacks::IOThreadHelper::IOThreadHelper(
+ CallbacksAssociatedPtrInfo callbacks_info,
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host)
+ : dispatcher_host_(std::move(dispatcher_host)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ callbacks_.Bind(std::move(callbacks_info));
+}
+
+IndexedDBCallbacks::IOThreadHelper::~IOThreadHelper() {}
+
+void IndexedDBCallbacks::IOThreadHelper::SendError(
+ const IndexedDBDatabaseError& error) {
+ callbacks_->Error(error.code(), error.message());
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessStringList(
+ const std::vector<base::string16>& value) {
+ callbacks_->SuccessStringList(value);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendBlocked(int64_t existing_version) {
+ callbacks_->Blocked(existing_version);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendUpgradeNeeded(
+ std::unique_ptr<DatabaseImpl> database,
+ int64_t old_version,
+ blink::WebIDBDataLoss data_loss,
+ const std::string& data_loss_message,
+ const content::IndexedDBDatabaseMetadata& metadata) {
+ ::indexed_db::mojom::DatabaseAssociatedPtrInfo ptr_info;
+ ::indexed_db::mojom::DatabaseAssociatedRequest request;
+ callbacks_.associated_group()->CreateAssociatedInterface(
+ mojo::AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request);
+ mojo::MakeStrongAssociatedBinding(std::move(database), std::move(request));
+ callbacks_->UpgradeNeeded(std::move(ptr_info), old_version, data_loss,
+ data_loss_message, metadata);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessDatabase(
+ std::unique_ptr<DatabaseImpl> database,
+ const content::IndexedDBDatabaseMetadata& metadata) {
+ ::indexed_db::mojom::DatabaseAssociatedPtrInfo ptr_info;
+ if (database) {
+ ::indexed_db::mojom::DatabaseAssociatedRequest request;
+ callbacks_.associated_group()->CreateAssociatedInterface(
+ mojo::AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request);
+ mojo::MakeStrongAssociatedBinding(std::move(database), std::move(request));
+ }
+ callbacks_->SuccessDatabase(std::move(ptr_info), metadata);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
+ int32_t cursor_id,
+ const IndexedDBKey& key,
+ const IndexedDBKey& primary_key,
+ ::indexed_db::mojom::ValuePtr value,
+ const std::vector<IndexedDBBlobInfo>& blob_info) {
+ if (!value || CreateAllBlobs(blob_info, &value->blob_or_file_info))
+ callbacks_->SuccessCursor(cursor_id, key, primary_key, std::move(value));
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessValue(
+ ::indexed_db::mojom::ReturnValuePtr value,
+ const std::vector<IndexedDBBlobInfo>& blob_info) {
+ if (!value || CreateAllBlobs(blob_info, &value->value->blob_or_file_info))
+ callbacks_->SuccessValue(std::move(value));
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessArray(
+ std::vector<::indexed_db::mojom::ReturnValuePtr> mojo_values,
+ const std::vector<IndexedDBReturnValue>& values) {
+ DCHECK_EQ(mojo_values.size(), values.size());
+
+ for (size_t i = 0; i < mojo_values.size(); ++i) {
+ if (!CreateAllBlobs(values[i].blob_info,
+ &mojo_values[i]->value->blob_or_file_info))
+ return;
+ }
+ callbacks_->SuccessArray(std::move(mojo_values));
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessKey(
+ const IndexedDBKey& value) {
+ callbacks_->SuccessKey(value);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccessInteger(int64_t value) {
+ callbacks_->SuccessInteger(value);
+}
+
+void IndexedDBCallbacks::IOThreadHelper::SendSuccess() {
+ callbacks_->Success();
+}
+
+std::string IndexedDBCallbacks::IOThreadHelper::CreateBlobData(
+ const IndexedDBBlobInfo& blob_info) {
+ if (!blob_info.uuid().empty()) {
+ // We're sending back a live blob, not a reference into our backing store.
+ return dispatcher_host_->HoldBlobData(blob_info);
+ }
+ scoped_refptr<ShareableFileReference> shareable_file =
+ ShareableFileReference::Get(blob_info.file_path());
+ if (!shareable_file) {
+ shareable_file = ShareableFileReference::GetOrCreate(
+ blob_info.file_path(),
+ ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
+ dispatcher_host_->context()->TaskRunner());
+ if (!blob_info.release_callback().is_null())
+ shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
+ }
+ return dispatcher_host_->HoldBlobData(blob_info);
+}
+
+bool IndexedDBCallbacks::IOThreadHelper::CreateAllBlobs(
+ const std::vector<IndexedDBBlobInfo>& blob_info,
+ std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
+ IDB_TRACE("IndexedDBCallbacks::CreateAllBlobs");
+ DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
+ if (!dispatcher_host_->blob_storage_context())
+ return false;
+ for (size_t i = 0; i < blob_info.size(); ++i)
+ (*blob_or_file_info)[i]->uuid = CreateBlobData(blob_info[i]);
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index 088c1633305..19f2b9e8809 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -15,8 +15,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
+#include "base/threading/thread_checker.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
+#include "content/common/indexed_db/indexed_db.mojom.h"
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "url/origin.h"
@@ -26,7 +28,6 @@ class IndexedDBBlobInfo;
class IndexedDBConnection;
class IndexedDBCursor;
class IndexedDBDatabase;
-class IndexedDBDatabaseCallbacks;
struct IndexedDBDataLossInfo;
struct IndexedDBDatabaseMetadata;
struct IndexedDBReturnValue;
@@ -46,13 +47,11 @@ class CONTENT_EXPORT IndexedDBCallbacks
int32_t ipc_callbacks_id,
int32_t ipc_cursor_id);
- // IndexedDBDatabase responses
- IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
- int32_t ipc_thread_id,
- int32_t ipc_callbacks_id,
- int32_t ipc_database_callbacks_id,
- int64_t host_transaction_id,
- const url::Origin& origin);
+ // Mojo-based responses
+ IndexedDBCallbacks(
+ IndexedDBDispatcherHost* dispatcher_host,
+ const url::Origin& origin,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info);
virtual void OnError(const IndexedDBDatabaseError& error);
@@ -93,8 +92,7 @@ class CONTENT_EXPORT IndexedDBCallbacks
virtual void OnSuccess(IndexedDBReturnValue* value);
// IndexedDBDatabase::GetAll
- virtual void OnSuccessArray(std::vector<IndexedDBReturnValue>* values,
- const IndexedDBKeyPath& key_path);
+ virtual void OnSuccessArray(std::vector<IndexedDBReturnValue>* values);
// IndexedDBDatabase::Put / IndexedDBCursor::Update
virtual void OnSuccess(const IndexedDBKey& key);
@@ -113,6 +111,10 @@ class CONTENT_EXPORT IndexedDBCallbacks
void SetConnectionOpenStartTime(const base::TimeTicks& start_time);
+ void set_host_transaction_id(int64_t host_transaction_id) {
+ host_transaction_id_ = host_transaction_id;
+ }
+
protected:
virtual ~IndexedDBCallbacks();
@@ -122,6 +124,8 @@ class CONTENT_EXPORT IndexedDBCallbacks
friend class base::RefCounted<IndexedDBCallbacks>;
+ class IOThreadHelper;
+
// Originally from IndexedDBCallbacks:
scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_;
int32_t ipc_callbacks_id_;
@@ -133,8 +137,7 @@ class CONTENT_EXPORT IndexedDBCallbacks
// IndexedDBDatabase callbacks ------------------------
int64_t host_transaction_id_;
url::Origin origin_;
- int32_t ipc_database_id_;
- int32_t ipc_database_callbacks_id_;
+ bool database_sent_ = false;
// Used to assert that OnSuccess is only called if there was no data loss.
blink::WebIDBDataLoss data_loss_;
@@ -142,6 +145,10 @@ class CONTENT_EXPORT IndexedDBCallbacks
// The "blocked" event should be sent at most once per request.
bool sent_blocked_;
base::TimeTicks connection_open_start_time_;
+
+ std::unique_ptr<IOThreadHelper, BrowserThread::DeleteOnIOThread> io_helper_;
+ base::ThreadChecker thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(IndexedDBCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_class_factory.h b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
index 60f069e6c96..f8b359d15f1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
@@ -25,7 +25,6 @@ namespace content {
class IndexedDBBackingStore;
class IndexedDBConnection;
-class IndexedDBDatabaseCallbacks;
class IndexedDBFactory;
class IndexedDBTransaction;
class LevelDBDatabase;
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.cc b/chromium/content/browser/indexed_db/indexed_db_connection.cc
index a749154090b..0c3cb35c010 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.cc
@@ -8,18 +8,22 @@
namespace content {
+namespace {
+
+static int32_t next_id;
+
+} // namespace
+
IndexedDBConnection::IndexedDBConnection(
scoped_refptr<IndexedDBDatabase> database,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks)
- : database_(database), callbacks_(callbacks), weak_factory_(this) {}
+ : id_(next_id++),
+ database_(database),
+ callbacks_(callbacks),
+ weak_factory_(this) {}
IndexedDBConnection::~IndexedDBConnection() {}
-void IndexedDBConnection::set_id(int32_t id) {
- DCHECK_EQ(id_, kInvalidId);
- id_ = id;
-}
-
void IndexedDBConnection::Close() {
if (!callbacks_.get())
return;
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.h b/chromium/content/browser/indexed_db/indexed_db_connection.h
index d8b72dfc1c2..ce60ebd8cc5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.h
@@ -16,7 +16,6 @@
#include "content/browser/indexed_db/indexed_db_observer.h"
namespace content {
-class IndexedDBDatabaseError;
class CONTENT_EXPORT IndexedDBConnection {
public:
@@ -38,7 +37,6 @@ class CONTENT_EXPORT IndexedDBConnection {
// connection.
virtual void RemoveObservers(const std::vector<int32_t>& remove_observer_ids);
- void set_id(int32_t id);
int32_t id() const { return id_; }
IndexedDBDatabase* database() const { return database_.get(); }
@@ -52,9 +50,7 @@ class CONTENT_EXPORT IndexedDBConnection {
}
private:
- enum { kInvalidId = -1 };
- // id_ is ipc_database_id
- int32_t id_ = kInvalidId;
+ const int32_t id_;
// NULL in some unit tests, and after the connection is closed.
scoped_refptr<IndexedDBDatabase> database_;
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 0dce05aa71c..8300e147e2b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -149,9 +149,9 @@ std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() {
std::vector<IndexedDBInfo> result;
for (const auto& origin : origins) {
size_t connection_count = GetConnectionCount(origin);
- result.push_back(
- IndexedDBInfo(GURL(origin.Serialize()), GetOriginDiskUsage(origin),
- GetOriginLastModified(origin), connection_count));
+ result.push_back(IndexedDBInfo(origin.GetURL(), GetOriginDiskUsage(origin),
+ GetOriginLastModified(origin),
+ connection_count));
}
return result;
}
@@ -335,7 +335,7 @@ void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) {
} else {
// LevelDB does not delete empty directories; work around this.
// TODO(jsbell): Remove when upstream bug is fixed.
- // https://code.google.com/p/leveldb/issues/detail?id=209
+ // https://github.com/google/leveldb/issues/215
const bool kNonRecursive = false;
base::DeleteFile(idb_directory, kNonRecursive);
}
@@ -439,7 +439,7 @@ void IndexedDBContextImpl::ConnectionOpened(const Origin& origin,
IndexedDBConnection* connection) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
quota_manager_proxy()->NotifyStorageAccessed(
- storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()),
+ storage::QuotaClient::kIndexedDatabase, origin.GetURL(),
storage::kStorageTypeTemporary);
if (AddToOriginSet(origin)) {
// A newly created db, notify the quota system.
@@ -453,7 +453,7 @@ void IndexedDBContextImpl::ConnectionClosed(const Origin& origin,
IndexedDBConnection* connection) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
quota_manager_proxy()->NotifyStorageAccessed(
- storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()),
+ storage::QuotaClient::kIndexedDatabase, origin.GetURL(),
storage::kStorageTypeTemporary);
if (factory_.get() && factory_->GetConnectionCount(origin) == 0)
QueryDiskAndUpdateQuotaUsage(origin);
@@ -499,8 +499,7 @@ IndexedDBContextImpl::~IndexedDBContextImpl() {
// static
base::FilePath IndexedDBContextImpl::GetBlobStoreFileName(
const Origin& origin) {
- std::string origin_id =
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize()));
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin.GetURL());
return base::FilePath()
.AppendASCII(origin_id)
.AddExtension(kIndexedDBExtension)
@@ -509,8 +508,7 @@ base::FilePath IndexedDBContextImpl::GetBlobStoreFileName(
// static
base::FilePath IndexedDBContextImpl::GetLevelDBFileName(const Origin& origin) {
- std::string origin_id =
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize()));
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin.GetURL());
return base::FilePath()
.AppendASCII(origin_id)
.AddExtension(kIndexedDBExtension)
@@ -551,7 +549,7 @@ void IndexedDBContextImpl::QueryDiskAndUpdateQuotaUsage(const Origin& origin) {
if (difference) {
origin_size_map_[origin] = current_disk_usage;
quota_manager_proxy()->NotifyStorageModified(
- storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()),
+ storage::QuotaClient::kIndexedDatabase, origin.GetURL(),
storage::kStorageTypeTemporary, difference);
}
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index 10821c3c0b8..85b6f9d6911 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -10,7 +10,6 @@
#include <set>
#include "base/auto_reset.h"
-#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -383,10 +382,7 @@ IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
IndexedDBDatabaseMetadata::NO_VERSION,
kInvalidId),
identifier_(unique_identifier),
- factory_(factory),
- experimental_web_platform_features_enabled_(
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
+ factory_(factory) {
DCHECK(factory != NULL);
}
@@ -934,7 +930,7 @@ void IndexedDBDatabase::SendObservations(
for (auto* conn : connections_) {
auto it = changes_map.find(conn->id());
if (it != changes_map.end())
- conn->callbacks()->OnDatabaseChange(it->first, std::move(it->second));
+ conn->callbacks()->OnDatabaseChange(std::move(it->second));
}
}
@@ -1210,7 +1206,7 @@ void IndexedDBDatabase::GetAllOperation(
if (!cursor) {
// Doesn't matter if key or value array here - will be empty array when it
// hits JavaScript.
- callbacks->OnSuccessArray(&found_values, object_store_metadata.key_path);
+ callbacks->OnSuccessArray(&found_values);
return;
}
@@ -1276,7 +1272,7 @@ void IndexedDBDatabase::GetAllOperation(
// to return an array of keys - no need to create our own array of keys.
callbacks->OnSuccess(IndexedDBKey(found_keys));
} else {
- callbacks->OnSuccessArray(&found_values, object_store_metadata.key_path);
+ callbacks->OnSuccessArray(&found_values);
}
}
@@ -1323,7 +1319,7 @@ struct IndexedDBDatabase::PutOperationParams {
std::unique_ptr<IndexedDBKey> key;
blink::WebIDBPutMode put_mode;
scoped_refptr<IndexedDBCallbacks> callbacks;
- std::vector<IndexKeys> index_keys;
+ std::vector<IndexedDBIndexKeys> index_keys;
private:
DISALLOW_COPY_AND_ASSIGN(PutOperationParams);
@@ -1337,7 +1333,7 @@ void IndexedDBDatabase::Put(
std::unique_ptr<IndexedDBKey> key,
blink::WebIDBPutMode put_mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::vector<IndexKeys>& index_keys) {
+ const std::vector<IndexedDBIndexKeys>& index_keys) {
IDB_TRACE1("IndexedDBDatabase::Put", "txn.id", transaction_id);
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
@@ -1505,10 +1501,11 @@ void IndexedDBDatabase::PutOperation(std::unique_ptr<PutOperationParams> params,
IndexedDBKeyRange(*key));
}
-void IndexedDBDatabase::SetIndexKeys(int64_t transaction_id,
- int64_t object_store_id,
- std::unique_ptr<IndexedDBKey> primary_key,
- const std::vector<IndexKeys>& index_keys) {
+void IndexedDBDatabase::SetIndexKeys(
+ int64_t transaction_id,
+ int64_t object_store_id,
+ std::unique_ptr<IndexedDBKey> primary_key,
+ const std::vector<IndexedDBIndexKeys>& index_keys) {
IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id);
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
@@ -1838,11 +1835,7 @@ void IndexedDBDatabase::DeleteRangeOperation(
}
return;
}
- if (experimental_web_platform_features_enabled_) {
- callbacks->OnSuccess(base::checked_cast<int64_t>(delete_count));
- } else {
- callbacks->OnSuccess();
- }
+ callbacks->OnSuccess();
FilterObservation(transaction, object_store_id, blink::WebIDBDelete,
*key_range);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index be8fdd0bb65..49cf2372f38 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -21,11 +21,11 @@
#include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
-#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/indexed_db_observer.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "content/browser/indexed_db/list_set.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
namespace url {
@@ -34,14 +34,12 @@ class Origin;
namespace content {
-class IndexedDBBlobInfo;
class IndexedDBConnection;
class IndexedDBDatabaseCallbacks;
class IndexedDBFactory;
class IndexedDBKey;
class IndexedDBKeyPath;
class IndexedDBKeyRange;
-class IndexedDBObservation;
class IndexedDBObserverChanges;
class IndexedDBTransaction;
struct IndexedDBValue;
@@ -49,9 +47,6 @@ struct IndexedDBValue;
class CONTENT_EXPORT IndexedDBDatabase
: NON_EXPORTED_BASE(public base::RefCounted<IndexedDBDatabase>) {
public:
- // An index and corresponding set of keys
- using IndexKeys = std::pair<int64_t, std::vector<IndexedDBKey>>;
-
// Identifier is pair of (origin, database name).
using Identifier = std::pair<url::Origin, base::string16>;
@@ -177,11 +172,11 @@ class CONTENT_EXPORT IndexedDBDatabase
std::unique_ptr<IndexedDBKey> key,
blink::WebIDBPutMode mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::vector<IndexKeys>& index_keys);
+ const std::vector<IndexedDBIndexKeys>& index_keys);
void SetIndexKeys(int64_t transaction_id,
int64_t object_store_id,
std::unique_ptr<IndexedDBKey> primary_key,
- const std::vector<IndexKeys>& index_keys);
+ const std::vector<IndexedDBIndexKeys>& index_keys);
void SetIndexesReady(int64_t transaction_id,
int64_t object_store_id,
const std::vector<int64_t>& index_ids);
@@ -352,8 +347,6 @@ class CONTENT_EXPORT IndexedDBDatabase
// synchronously.
bool processing_pending_requests_ = false;
- bool experimental_web_platform_features_enabled_;
-
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
index ab09e9074de..d9aa90af00b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -4,73 +4,136 @@
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/indexed_db/indexed_db_observer_changes.h"
#include "content/common/indexed_db/indexed_db_messages.h"
+using ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
+
namespace content {
+class IndexedDBDatabaseCallbacks::IOThreadHelper {
+ public:
+ explicit IOThreadHelper(DatabaseCallbacksAssociatedPtrInfo callbacks_info);
+ ~IOThreadHelper();
+
+ void SendForcedClose();
+ void SendVersionChange(int64_t old_version, int64_t new_version);
+ void SendAbort(int64_t transaction_id, const IndexedDBDatabaseError& error);
+ void SendComplete(int64_t transaction_id);
+
+ private:
+ ::indexed_db::mojom::DatabaseCallbacksAssociatedPtr callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(IOThreadHelper);
+};
+
IndexedDBDatabaseCallbacks::IndexedDBDatabaseCallbacks(
- IndexedDBDispatcherHost* dispatcher_host,
- int ipc_thread_id,
- int ipc_database_callbacks_id)
- : dispatcher_host_(dispatcher_host),
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ int32_t ipc_thread_id,
+ DatabaseCallbacksAssociatedPtrInfo callbacks_info)
+ : dispatcher_host_(std::move(dispatcher_host)),
ipc_thread_id_(ipc_thread_id),
- ipc_database_callbacks_id_(ipc_database_callbacks_id) {}
+ io_helper_(new IOThreadHelper(std::move(callbacks_info))) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ thread_checker_.DetachFromThread();
+}
-IndexedDBDatabaseCallbacks::~IndexedDBDatabaseCallbacks() {}
+IndexedDBDatabaseCallbacks::~IndexedDBDatabaseCallbacks() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
void IndexedDBDatabaseCallbacks::OnForcedClose() {
- if (!dispatcher_host_.get())
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!dispatcher_host_)
return;
- dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksForcedClose(
- ipc_thread_id_, ipc_database_callbacks_id_));
-
+ DCHECK(io_helper_);
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendForcedClose,
+ base::Unretained(io_helper_.get())));
dispatcher_host_ = NULL;
}
void IndexedDBDatabaseCallbacks::OnVersionChange(int64_t old_version,
int64_t new_version) {
- if (!dispatcher_host_.get())
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!dispatcher_host_)
return;
- dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksVersionChange(
- ipc_thread_id_, ipc_database_callbacks_id_, old_version, new_version));
+ DCHECK(io_helper_);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendVersionChange,
+ base::Unretained(io_helper_.get()), old_version, new_version));
}
void IndexedDBDatabaseCallbacks::OnAbort(int64_t host_transaction_id,
const IndexedDBDatabaseError& error) {
- if (!dispatcher_host_.get())
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!dispatcher_host_)
return;
dispatcher_host_->FinishTransaction(host_transaction_id, false);
- dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksAbort(
- ipc_thread_id_,
- ipc_database_callbacks_id_,
- dispatcher_host_->RendererTransactionId(host_transaction_id),
- error.code(),
- error.message()));
+ DCHECK(io_helper_);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendAbort, base::Unretained(io_helper_.get()),
+ dispatcher_host_->RendererTransactionId(host_transaction_id),
+ error));
}
void IndexedDBDatabaseCallbacks::OnComplete(int64_t host_transaction_id) {
- if (!dispatcher_host_.get())
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!dispatcher_host_)
return;
dispatcher_host_->FinishTransaction(host_transaction_id, true);
- dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksComplete(
- ipc_thread_id_,
- ipc_database_callbacks_id_,
- dispatcher_host_->RendererTransactionId(host_transaction_id)));
+ DCHECK(io_helper_);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&IOThreadHelper::SendComplete,
+ base::Unretained(io_helper_.get()),
+ dispatcher_host_->RendererTransactionId(host_transaction_id)));
}
void IndexedDBDatabaseCallbacks::OnDatabaseChange(
- int32_t ipc_database_id,
std::unique_ptr<IndexedDBObserverChanges> changes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(io_helper_);
dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksChanges(
- ipc_thread_id_, ipc_database_id,
+ ipc_thread_id_,
IndexedDBDispatcherHost::ConvertObserverChanges(std::move(changes))));
}
+IndexedDBDatabaseCallbacks::IOThreadHelper::IOThreadHelper(
+ DatabaseCallbacksAssociatedPtrInfo callbacks_info) {
+ callbacks_.Bind(std::move(callbacks_info));
+}
+
+IndexedDBDatabaseCallbacks::IOThreadHelper::~IOThreadHelper() {}
+
+void IndexedDBDatabaseCallbacks::IOThreadHelper::SendForcedClose() {
+ callbacks_->ForcedClose();
+}
+
+void IndexedDBDatabaseCallbacks::IOThreadHelper::SendVersionChange(
+ int64_t old_version,
+ int64_t new_version) {
+ callbacks_->VersionChange(old_version, new_version);
+}
+
+void IndexedDBDatabaseCallbacks::IOThreadHelper::SendAbort(
+ int64_t transaction_id,
+ const IndexedDBDatabaseError& error) {
+ callbacks_->Abort(transaction_id, error.code(), error.message());
+}
+
+void IndexedDBDatabaseCallbacks::IOThreadHelper::SendComplete(
+ int64_t transaction_id) {
+ callbacks_->Complete(transaction_id);
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
index 0ee97afccf6..5a12bdf4a57 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.h
@@ -9,7 +9,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
+#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "content/public/browser/browser_thread.h"
namespace content {
class IndexedDBDatabaseError;
@@ -19,9 +22,10 @@ class IndexedDBObserverChanges;
class CONTENT_EXPORT IndexedDBDatabaseCallbacks
: public base::RefCounted<IndexedDBDatabaseCallbacks> {
public:
- IndexedDBDatabaseCallbacks(IndexedDBDispatcherHost* dispatcher_host,
- int ipc_thread_id,
- int ipc_database_callbacks_id);
+ IndexedDBDatabaseCallbacks(
+ scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
+ int32_t ipc_thread_id,
+ ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo callbacks_info);
virtual void OnForcedClose();
virtual void OnVersionChange(int64_t old_version, int64_t new_version);
@@ -30,7 +34,6 @@ class CONTENT_EXPORT IndexedDBDatabaseCallbacks
const IndexedDBDatabaseError& error);
virtual void OnComplete(int64_t host_transaction_id);
virtual void OnDatabaseChange(
- int32_t ipc_database_id,
std::unique_ptr<IndexedDBObserverChanges> changes);
protected:
@@ -39,9 +42,12 @@ class CONTENT_EXPORT IndexedDBDatabaseCallbacks
private:
friend class base::RefCounted<IndexedDBDatabaseCallbacks>;
+ class IOThreadHelper;
+
scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_;
- int ipc_thread_id_;
- int ipc_database_callbacks_id_;
+ int32_t ipc_thread_id_;
+ std::unique_ptr<IOThreadHelper, BrowserThread::DeleteOnIOThread> io_helper_;
+ base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
index e558e7bc111..a13a1631903 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -27,6 +27,7 @@
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_factory.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -37,7 +38,12 @@ const int kFakeChildProcessId = 0;
namespace content {
-TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
+class IndexedDBDatabaseTest : public ::testing::Test {
+ private:
+ TestBrowserThreadBundle thread_bundle_;
+};
+
+TEST_F(IndexedDBDatabaseTest, BackingStoreRetention) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
@@ -56,7 +62,7 @@ TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
EXPECT_TRUE(backing_store->HasOneRef()); // local
}
-TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
+TEST_F(IndexedDBDatabaseTest, ConnectionLifecycle) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
@@ -110,7 +116,7 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
db = NULL;
}
-TEST(IndexedDBDatabaseTest, ForcedClose) {
+TEST_F(IndexedDBDatabaseTest, ForcedClose) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
@@ -177,7 +183,7 @@ class MockCallbacks : public IndexedDBCallbacks {
DISALLOW_COPY_AND_ASSIGN(MockCallbacks);
};
-TEST(IndexedDBDatabaseTest, PendingDelete) {
+TEST_F(IndexedDBDatabaseTest, PendingDelete) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
@@ -233,7 +239,7 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
EXPECT_TRUE(request2->success_called());
}
-TEST(IndexedDBDatabaseTest, ConnectionRequestsNoLongerValid) {
+TEST_F(IndexedDBDatabaseTest, ConnectionRequestsNoLongerValid) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
@@ -390,8 +396,8 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
leveldb::Status commit_success_;
private:
- base::MessageLoop message_loop_;
scoped_refptr<MockIndexedDBFactory> factory_;
+ content::TestBrowserThreadBundle thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
};
@@ -505,7 +511,7 @@ TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
std::unique_ptr<IndexedDBKey> key(base::MakeUnique<IndexedDBKey>("key"));
- std::vector<IndexedDBDatabase::IndexKeys> index_keys;
+ std::vector<IndexedDBIndexKeys> index_keys;
scoped_refptr<MockIndexedDBCallbacks> request(
new MockIndexedDBCallbacks(false));
db_->Put(transaction_->id(), store_id, &value, &handles, std::move(key),
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index dba6ec6b234..01df072d4e0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -15,19 +15,18 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/bad_message.h"
-#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
-#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/indexed_db_observation.h"
#include "content/browser/indexed_db/indexed_db_observer_changes.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/renderer_host/render_message_filter.h"
#include "content/common/indexed_db/indexed_db_messages.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
@@ -35,7 +34,6 @@
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/database/database_util.h"
-#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "url/origin.h"
@@ -47,6 +45,8 @@ namespace content {
namespace {
+const char kInvalidOrigin[] = "Origin is invalid";
+
bool IsValidOrigin(const url::Origin& origin) {
return !origin.unique();
}
@@ -59,16 +59,20 @@ IndexedDBDispatcherHost::IndexedDBDispatcherHost(
IndexedDBContextImpl* indexed_db_context,
ChromeBlobStorageContext* blob_storage_context)
: BrowserMessageFilter(IndexedDBMsgStart),
+ BrowserAssociatedInterface(this, this),
request_context_getter_(request_context_getter),
indexed_db_context_(indexed_db_context),
blob_storage_context_(blob_storage_context),
- database_dispatcher_host_(base::MakeUnique<DatabaseDispatcherHost>(this)),
cursor_dispatcher_host_(base::MakeUnique<CursorDispatcherHost>(this)),
ipc_process_id_(ipc_process_id) {
DCHECK(indexed_db_context_.get());
}
-IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {}
+IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {
+ // TODO(alecflett): uncomment these when we find the source of these leaks.
+ // DCHECK(transaction_size_map_.empty());
+ // DCHECK(transaction_origin_map_.empty());
+}
void IndexedDBDispatcherHost::OnChannelClosing() {
bool success = indexed_db_context_->TaskRunner()->PostTask(
@@ -98,11 +102,6 @@ void IndexedDBDispatcherHost::ResetDispatcherHosts() {
// Prevent any pending connections from being processed.
is_open_ = false;
- // Note that we explicitly separate CloseAll() from destruction of the
- // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to
- // be dispatched through database_dispatcher_host_.
- database_dispatcher_host_->CloseAll();
- database_dispatcher_host_.reset();
cursor_dispatcher_host_.reset();
}
@@ -112,7 +111,6 @@ base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage(
return NULL;
switch (message.type()) {
- case IndexedDBHostMsg_DatabasePut::ID:
case IndexedDBHostMsg_AckReceivedBlobs::ID:
return NULL;
default:
@@ -125,20 +123,13 @@ bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) {
return false;
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() ||
- (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
- message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID));
+ message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID);
- bool handled = database_dispatcher_host_->OnMessageReceived(message) ||
- cursor_dispatcher_host_->OnMessageReceived(message);
+ bool handled = cursor_dispatcher_host_->OnMessageReceived(message);
if (!handled) {
handled = true;
IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcherHost, message)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames,
- OnIDBFactoryGetDatabaseNames)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryDeleteDatabase,
- OnIDBFactoryDeleteDatabase)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_AckReceivedBlobs, OnAckReceivedBlobs)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -153,28 +144,27 @@ int32_t IndexedDBDispatcherHost::Add(IndexedDBCursor* cursor) {
return cursor_dispatcher_host_->map_.Add(cursor);
}
-int32_t IndexedDBDispatcherHost::Add(IndexedDBConnection* connection,
- int32_t ipc_thread_id,
- const url::Origin& origin) {
- if (!database_dispatcher_host_) {
- connection->Close();
- delete connection;
- return -1;
- }
- int32_t ipc_database_id = database_dispatcher_host_->map_.Add(connection);
- connection->set_id(ipc_database_id);
- context()->ConnectionOpened(origin, connection);
- database_dispatcher_host_->database_origin_map_[ipc_database_id] = origin;
- return ipc_database_id;
+bool IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id,
+ const url::Origin& origin) {
+ if (base::ContainsKey(transaction_size_map_, host_transaction_id))
+ return false;
+ transaction_size_map_[host_transaction_id] = 0;
+ transaction_origin_map_[host_transaction_id] = origin;
+ return true;
}
-void IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id,
- const url::Origin& origin) {
- if (!database_dispatcher_host_)
- return;
- database_dispatcher_host_->transaction_size_map_[host_transaction_id] = 0;
- database_dispatcher_host_->transaction_origin_map_[host_transaction_id] =
- origin;
+bool IndexedDBDispatcherHost::GetTransactionSize(int64_t host_transaction_id,
+ int64_t* transaction_size) {
+ const auto it = transaction_size_map_.find(host_transaction_id);
+ if (it == transaction_size_map_.end())
+ return false;
+ *transaction_size = it->second;
+ return true;
+}
+
+void IndexedDBDispatcherHost::AddToTransaction(int64_t host_transaction_id,
+ int64_t value_length) {
+ transaction_size_map_[host_transaction_id] += value_length;
}
int64_t IndexedDBDispatcherHost::HostTransactionId(int64_t transaction_id) {
@@ -262,40 +252,6 @@ IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(
return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id);
}
-::IndexedDBDatabaseMetadata IndexedDBDispatcherHost::ConvertMetadata(
- const content::IndexedDBDatabaseMetadata& web_metadata) {
- ::IndexedDBDatabaseMetadata metadata;
- metadata.id = web_metadata.id;
- metadata.name = web_metadata.name;
- metadata.version = web_metadata.version;
- metadata.max_object_store_id = web_metadata.max_object_store_id;
-
- for (const auto& iter : web_metadata.object_stores) {
- const content::IndexedDBObjectStoreMetadata& web_store_metadata =
- iter.second;
- ::IndexedDBObjectStoreMetadata idb_store_metadata;
- idb_store_metadata.id = web_store_metadata.id;
- idb_store_metadata.name = web_store_metadata.name;
- idb_store_metadata.key_path = web_store_metadata.key_path;
- idb_store_metadata.auto_increment = web_store_metadata.auto_increment;
- idb_store_metadata.max_index_id = web_store_metadata.max_index_id;
-
- for (const auto& index_iter : web_store_metadata.indexes) {
- const content::IndexedDBIndexMetadata& web_index_metadata =
- index_iter.second;
- ::IndexedDBIndexMetadata idb_index_metadata;
- idb_index_metadata.id = web_index_metadata.id;
- idb_index_metadata.name = web_index_metadata.name;
- idb_index_metadata.key_path = web_index_metadata.key_path;
- idb_index_metadata.unique = web_index_metadata.unique;
- idb_index_metadata.multi_entry = web_index_metadata.multi_entry;
- idb_store_metadata.indexes.push_back(idb_index_metadata);
- }
- metadata.object_stores.push_back(idb_store_metadata);
- }
- return metadata;
-}
-
IndexedDBMsg_ObserverChanges IndexedDBDispatcherHost::ConvertObserverChanges(
std::unique_ptr<IndexedDBObserverChanges> changes) {
IndexedDBMsg_ObserverChanges idb_changes;
@@ -315,79 +271,118 @@ IndexedDBMsg_Observation IndexedDBDispatcherHost::ConvertObservation(
return idb_observation;
}
-void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
- const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& params) {
- DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+void IndexedDBDispatcherHost::GetDatabaseNames(
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!IsValidOrigin(params.origin)) {
- bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
+ if (!IsValidOrigin(origin)) {
+ mojo::ReportBadMessage(kInvalidOrigin);
return;
}
- base::FilePath indexed_db_path = indexed_db_context_->data_path();
- context()->GetIDBFactory()->GetDatabaseNames(
- new IndexedDBCallbacks(this, params.ipc_thread_id,
- params.ipc_callbacks_id),
- params.origin, indexed_db_path, request_context_getter_);
+ scoped_refptr<IndexedDBCallbacks> callbacks(
+ new IndexedDBCallbacks(this, origin, std::move(callbacks_info)));
+ indexed_db_context_->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&IndexedDBDispatcherHost::GetDatabaseNamesOnIDBThread, this,
+ base::Passed(&callbacks), origin));
+}
+
+void IndexedDBDispatcherHost::Open(
+ int32_t worker_thread,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
+ database_callbacks_info,
+ const url::Origin& origin,
+ const base::string16& name,
+ int64_t version,
+ int64_t transaction_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!IsValidOrigin(origin)) {
+ mojo::ReportBadMessage(kInvalidOrigin);
+ return;
+ }
+
+ scoped_refptr<IndexedDBCallbacks> callbacks(
+ new IndexedDBCallbacks(this, origin, std::move(callbacks_info)));
+ scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks(
+ new IndexedDBDatabaseCallbacks(this, worker_thread,
+ std::move(database_callbacks_info)));
+ indexed_db_context_->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&IndexedDBDispatcherHost::OpenOnIDBThread, this,
+ base::Passed(&callbacks), base::Passed(&database_callbacks),
+ origin, name, version, transaction_id));
}
-void IndexedDBDispatcherHost::OnIDBFactoryOpen(
- const IndexedDBHostMsg_FactoryOpen_Params& params) {
- DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+void IndexedDBDispatcherHost::DeleteDatabase(
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ const url::Origin& origin,
+ const base::string16& name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!IsValidOrigin(params.origin)) {
- bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
+ if (!IsValidOrigin(origin)) {
+ mojo::ReportBadMessage(kInvalidOrigin);
return;
}
+ scoped_refptr<IndexedDBCallbacks> callbacks(
+ new IndexedDBCallbacks(this, origin, std::move(callbacks_info)));
+ indexed_db_context_->TaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&IndexedDBDispatcherHost::DeleteDatabaseOnIDBThread,
+ this, base::Passed(&callbacks), origin, name));
+}
+
+void IndexedDBDispatcherHost::GetDatabaseNamesOnIDBThread(
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin) {
+ DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+
+ base::FilePath indexed_db_path = indexed_db_context_->data_path();
+ context()->GetIDBFactory()->GetDatabaseNames(
+ callbacks, origin, indexed_db_path, request_context_getter_);
+}
+
+void IndexedDBDispatcherHost::OpenOnIDBThread(
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
+ const url::Origin& origin,
+ const base::string16& name,
+ int64_t version,
+ int64_t transaction_id) {
+ DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+
base::TimeTicks begin_time = base::TimeTicks::Now();
base::FilePath indexed_db_path = indexed_db_context_->data_path();
- int64_t host_transaction_id = HostTransactionId(params.transaction_id);
+ int64_t host_transaction_id = HostTransactionId(transaction_id);
// TODO(dgrogan): Don't let a non-existing database be opened (and therefore
// created) if this origin is already over quota.
- scoped_refptr<IndexedDBCallbacks> callbacks = new IndexedDBCallbacks(
- this, params.ipc_thread_id, params.ipc_callbacks_id,
- params.ipc_database_callbacks_id, host_transaction_id, params.origin);
callbacks->SetConnectionOpenStartTime(begin_time);
- scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks =
- new IndexedDBDatabaseCallbacks(
- this, params.ipc_thread_id, params.ipc_database_callbacks_id);
+ callbacks->set_host_transaction_id(host_transaction_id);
std::unique_ptr<IndexedDBPendingConnection> connection =
base::MakeUnique<IndexedDBPendingConnection>(
callbacks, database_callbacks, ipc_process_id_, host_transaction_id,
- params.version);
+ version);
DCHECK(request_context_getter_);
- context()->GetIDBFactory()->Open(params.name, std::move(connection),
- request_context_getter_, params.origin,
+ context()->GetIDBFactory()->Open(name, std::move(connection),
+ request_context_getter_, origin,
indexed_db_path);
}
-void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
- const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) {
+void IndexedDBDispatcherHost::DeleteDatabaseOnIDBThread(
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::string16& name) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- if (!IsValidOrigin(params.origin)) {
- bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
- return;
- }
-
base::FilePath indexed_db_path = indexed_db_context_->data_path();
DCHECK(request_context_getter_);
context()->GetIDBFactory()->DeleteDatabase(
- params.name, request_context_getter_,
- new IndexedDBCallbacks(this, params.ipc_thread_id,
- params.ipc_callbacks_id),
- params.origin, indexed_db_path);
-}
-
-// OnPutHelper exists only to allow us to hop threads while holding a reference
-// to the IndexedDBDispatcherHost.
-void IndexedDBDispatcherHost::OnPutHelper(
- const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles) {
- database_dispatcher_host_->OnPut(params, std::move(handles));
+ name, request_context_getter_, callbacks, origin, indexed_db_path);
}
void IndexedDBDispatcherHost::OnAckReceivedBlobs(
@@ -400,19 +395,12 @@ void IndexedDBDispatcherHost::OnAckReceivedBlobs(
void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id,
bool committed) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- if (!database_dispatcher_host_)
- return;
- TransactionIDToOriginMap& transaction_origin_map =
- database_dispatcher_host_->transaction_origin_map_;
- TransactionIDToSizeMap& transaction_size_map =
- database_dispatcher_host_->transaction_size_map_;
- TransactionIDToDatabaseIDMap& transaction_database_map =
- database_dispatcher_host_->transaction_database_map_;
- if (committed)
- context()->TransactionComplete(transaction_origin_map[host_transaction_id]);
- transaction_origin_map.erase(host_transaction_id);
- transaction_size_map.erase(host_transaction_id);
- transaction_database_map.erase(host_transaction_id);
+ if (committed) {
+ context()->TransactionComplete(
+ transaction_origin_map_[host_transaction_id]);
+ }
+ transaction_origin_map_.erase(host_transaction_id);
+ transaction_size_map_.erase(host_transaction_id);
}
//////////////////////////////////////////////////////////////////////
@@ -421,20 +409,6 @@ void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id,
template <typename ObjectType>
ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess(
- IDMap<ObjectType, IDMapOwnPointer>* map,
- int32_t ipc_return_object_id) {
- DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- ObjectType* return_object = map->Lookup(ipc_return_object_id);
- if (!return_object) {
- NOTREACHED() << "Uh oh, couldn't find object with id "
- << ipc_return_object_id;
- bad_message::ReceivedBadMessage(this, bad_message::IDBDH_GET_OR_TERMINATE);
- }
- return return_object;
-}
-
-template <typename ObjectType>
-ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess(
RefIDMap<ObjectType>* map,
int32_t ipc_return_object_id) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
@@ -455,556 +429,12 @@ void IndexedDBDispatcherHost::DestroyObject(MapType* map,
}
//////////////////////////////////////////////////////////////////////
-// IndexedDBDispatcherHost::DatabaseDispatcherHost
-//
-
-IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost(
- IndexedDBDispatcherHost* parent)
- : parent_(parent), weak_factory_(this) {
- map_.set_check_on_null_data(true);
-}
-
-IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() {
- // TODO(alecflett): uncomment these when we find the source of these leaks.
- // DCHECK(transaction_size_map_.empty());
- // DCHECK(transaction_origin_map_.empty());
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- // Abort outstanding transactions started by connections in the associated
- // front-end to unblock later transactions. This should only occur on unclean
- // (crash) or abrupt (process-kill) shutdowns.
- for (TransactionIDToDatabaseIDMap::iterator iter =
- transaction_database_map_.begin();
- iter != transaction_database_map_.end();) {
- int64_t transaction_id = iter->first;
- int32_t ipc_database_id = iter->second;
- ++iter;
- IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
- if (connection && connection->IsConnected()) {
- connection->database()->Abort(
- transaction_id,
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError));
- }
- }
- DCHECK(transaction_database_map_.empty());
-
- for (const auto& iter : database_origin_map_) {
- IndexedDBConnection* connection = map_.Lookup(iter.first);
- if (connection && connection->IsConnected()) {
- connection->Close();
- parent_->context()->ConnectionClosed(iter.second, connection);
- }
- }
-}
-
-bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
- const IPC::Message& message) {
- DCHECK((message.type() == IndexedDBHostMsg_DatabasePut::ID ||
- message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
- parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(
- IndexedDBDispatcherHost::DatabaseDispatcherHost, message)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore,
- OnCreateObjectStore)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore,
- OnDeleteObjectStore)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseRenameObjectStore,
- OnRenameObjectStore)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction,
- OnCreateTransaction)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseVersionChangeIgnored,
- OnVersionChangeIgnored)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseObserve, OnObserve)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseUnobserve, OnUnobserve)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGetAll, OnGetAll)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPutWrapper)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexKeys, OnSetIndexKeys)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexesReady,
- OnSetIndexesReady)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseOpenCursor, OnOpenCursor)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCount, OnCount)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteRange, OnDeleteRange)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClear, OnClear)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateIndex, OnCreateIndex)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteIndex, OnDeleteIndex)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseRenameIndex, OnRenameIndex)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseAbort, OnAbort)
- IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
- const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- int64_t host_transaction_id =
- parent_->HostTransactionId(params.transaction_id);
- connection->database()->CreateObjectStore(host_transaction_id,
- params.object_store_id,
- params.name,
- params.key_path,
- params.auto_increment);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore(
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->DeleteObjectStore(
- parent_->HostTransactionId(transaction_id), object_store_id);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnRenameObjectStore(
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& new_name) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->RenameObjectStore(
- parent_->HostTransactionId(transaction_id), object_store_id, new_name);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
- const IndexedDBHostMsg_DatabaseCreateTransaction_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- int64_t host_transaction_id =
- parent_->HostTransactionId(params.transaction_id);
-
- if (base::ContainsKey(transaction_database_map_, host_transaction_id)) {
- DLOG(ERROR) << "Duplicate host_transaction_id.";
- return;
- }
-
- connection->database()->CreateTransaction(
- host_transaction_id, connection, params.object_store_ids, params.mode);
- transaction_database_map_[host_transaction_id] = params.ipc_database_id;
- parent_->RegisterTransactionId(host_transaction_id,
- database_origin_map_[params.ipc_database_id]);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
- int32_t ipc_database_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
- connection->Close();
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnVersionChangeIgnored(
- int32_t ipc_database_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
- connection->VersionChangeIgnored();
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
- int32_t ipc_object_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_object_id);
- if (!connection)
- return;
- if (connection->IsConnected())
- connection->Close();
- parent_->context()->ConnectionClosed(database_origin_map_[ipc_object_id],
- connection);
- database_origin_map_.erase(ipc_object_id);
- parent_->DestroyObject(&map_, ipc_object_id);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnObserve(
- const IndexedDBHostMsg_DatabaseObserve_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
- IndexedDBObserver::Options options(params.include_transaction,
- params.no_records, params.values,
- params.operation_types);
- connection->database()->AddPendingObserver(
- parent_->HostTransactionId(params.transaction_id), params.observer_id,
- options);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnUnobserve(
- int32_t ipc_database_id,
- const std::vector<int32_t>& observer_ids_to_remove) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- DCHECK(!observer_ids_to_remove.empty());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
- connection->RemoveObservers(observer_ids_to_remove);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
- const IndexedDBHostMsg_DatabaseGet_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id));
- connection->database()->Get(
- parent_->HostTransactionId(params.transaction_id), params.object_store_id,
- params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
- params.key_only, callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGetAll(
- const IndexedDBHostMsg_DatabaseGetAll_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id));
- connection->database()->GetAll(
- parent_->HostTransactionId(params.transaction_id), params.object_store_id,
- params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
- params.key_only, params.max_count, callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper(
- const IndexedDBHostMsg_DatabasePut_Params& params) {
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
- for (const auto& info : params.value.blob_or_file_info) {
- handles.push_back(
- parent_->blob_storage_context_->context()->GetBlobDataFromUUID(
- info.uuid));
- }
- parent_->context()->TaskRunner()->PostTask(
- FROM_HERE, base::Bind(&IndexedDBDispatcherHost::OnPutHelper, parent_,
- params, base::Passed(&handles)));
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
- const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
-
- std::vector<std::unique_ptr<storage::BlobDataHandle>> scoped_handles;
- scoped_handles.swap(handles);
-
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id));
-
- int64_t host_transaction_id =
- parent_->HostTransactionId(params.transaction_id);
-
- std::vector<IndexedDBBlobInfo> blob_info(
- params.value.blob_or_file_info.size());
-
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- size_t i = 0;
- for (const auto& info : params.value.blob_or_file_info) {
- if (info.is_file) {
- base::FilePath path;
- if (!info.file_path.empty()) {
- path = base::FilePath::FromUTF16Unsafe(info.file_path);
- if (!policy->CanReadFile(parent_->ipc_process_id_, path)) {
- bad_message::ReceivedBadMessage(parent_,
- bad_message::IDBDH_CAN_READ_FILE);
- return;
- }
- }
- blob_info[i] =
- IndexedDBBlobInfo(info.uuid, path, info.file_name, info.mime_type);
- if (info.size != static_cast<uint64_t>(-1)) {
- blob_info[i].set_last_modified(
- base::Time::FromDoubleT(info.last_modified));
- blob_info[i].set_size(info.size);
- }
- } else {
- blob_info[i] = IndexedDBBlobInfo(info.uuid, info.mime_type, info.size);
- }
- ++i;
- }
-
- // TODO(alecflett): Avoid a copy here.
- IndexedDBValue value;
- value.bits = params.value.bits;
- value.blob_info.swap(blob_info);
- connection->database()->Put(host_transaction_id, params.object_store_id,
- &value, &scoped_handles,
- base::MakeUnique<IndexedDBKey>(params.key),
- params.put_mode, callbacks, params.index_keys);
- // Size can't be big enough to overflow because it represents the
- // actual bytes passed through IPC.
- transaction_size_map_[host_transaction_id] += params.value.bits.size();
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys(
- const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- int64_t host_transaction_id =
- parent_->HostTransactionId(params.transaction_id);
- connection->database()->SetIndexKeys(
- host_transaction_id, params.object_store_id,
- base::MakeUnique<IndexedDBKey>(params.primary_key), params.index_keys);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady(
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- const std::vector<int64_t>& index_ids) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->SetIndexesReady(
- parent_->HostTransactionId(transaction_id), object_store_id, index_ids);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
- const IndexedDBHostMsg_DatabaseOpenCursor_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id, -1));
- connection->database()->OpenCursor(
- parent_->HostTransactionId(params.transaction_id), params.object_store_id,
- params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
- params.direction, params.key_only, params.task_type, callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount(
- const IndexedDBHostMsg_DatabaseCount_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id));
- connection->database()->Count(
- parent_->HostTransactionId(params.transaction_id), params.object_store_id,
- params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
- callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange(
- const IndexedDBHostMsg_DatabaseDeleteRange_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
- parent_, params.ipc_thread_id, params.ipc_callbacks_id));
- connection->database()->DeleteRange(
- parent_->HostTransactionId(params.transaction_id), params.object_store_id,
- base::MakeUnique<IndexedDBKeyRange>(params.key_range), callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear(
- int32_t ipc_thread_id,
- int32_t ipc_callbacks_id,
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- scoped_refptr<IndexedDBCallbacks> callbacks(
- new IndexedDBCallbacks(parent_, ipc_thread_id, ipc_callbacks_id));
-
- connection->database()->Clear(
- parent_->HostTransactionId(transaction_id), object_store_id, callbacks);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort(
- int32_t ipc_database_id,
- int64_t transaction_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->Abort(parent_->HostTransactionId(transaction_id));
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit(
- int32_t ipc_database_id,
- int64_t transaction_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
- // May have been aborted by back end before front-end could request commit.
- if (!base::ContainsKey(transaction_size_map_, host_transaction_id))
- return;
- int64_t transaction_size = transaction_size_map_[host_transaction_id];
-
- // Always allow empty or delete-only transactions.
- if (!transaction_size) {
- connection->database()->Commit(host_transaction_id);
- return;
- }
-
- parent_->context()->quota_manager_proxy()->GetUsageAndQuota(
- parent_->context()->TaskRunner(),
- GURL(transaction_origin_map_[host_transaction_id].Serialize()),
- storage::kStorageTypeTemporary,
- base::Bind(&IndexedDBDispatcherHost::DatabaseDispatcherHost::
- OnGotUsageAndQuotaForCommit,
- weak_factory_.GetWeakPtr(), ipc_database_id, transaction_id));
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::
- OnGotUsageAndQuotaForCommit(int32_t ipc_database_id,
- int64_t transaction_id,
- storage::QuotaStatusCode status,
- int64_t usage,
- int64_t quota) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
- // May have disconnected while quota check was pending.
- if (!connection || !connection->IsConnected())
- return;
- int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
- // May have aborted while quota check was pending.
- if (!base::ContainsKey(transaction_size_map_, host_transaction_id))
- return;
- int64_t transaction_size = transaction_size_map_[host_transaction_id];
-
- if (status == storage::kQuotaStatusOk &&
- usage + transaction_size <= quota) {
- connection->database()->Commit(host_transaction_id);
- } else {
- connection->database()->Abort(
- host_transaction_id,
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
- }
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
- const IndexedDBHostMsg_DatabaseCreateIndex_Params& params) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- int64_t host_transaction_id =
- parent_->HostTransactionId(params.transaction_id);
- connection->database()->CreateIndex(host_transaction_id,
- params.object_store_id,
- params.index_id,
- params.name,
- params.key_path,
- params.unique,
- params.multi_entry);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex(
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->DeleteIndex(
- parent_->HostTransactionId(transaction_id), object_store_id, index_id);
-}
-
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnRenameIndex(
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& new_name) {
- DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
- IndexedDBConnection* connection =
- parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection || !connection->IsConnected())
- return;
-
- connection->database()->RenameIndex(
- parent_->HostTransactionId(transaction_id), object_store_id, index_id,
- new_name);
-}
-
-//////////////////////////////////////////////////////////////////////
// IndexedDBDispatcherHost::CursorDispatcherHost
//
IndexedDBDispatcherHost::CursorDispatcherHost::CursorDispatcherHost(
IndexedDBDispatcherHost* parent)
: parent_(parent) {
- map_.set_check_on_null_data(true);
}
IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {}
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
index d59ba81a6f4..e5d7b8d983a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -16,30 +16,15 @@
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/quota/quota_manager.h"
-#include "storage/common/quota/quota_status_code.h"
#include "url/gurl.h"
-struct IndexedDBDatabaseMetadata;
-struct IndexedDBHostMsg_DatabaseCount_Params;
-struct IndexedDBHostMsg_DatabaseCreateIndex_Params;
-struct IndexedDBHostMsg_DatabaseCreateObjectStore_Params;
-struct IndexedDBHostMsg_DatabaseCreateTransaction_Params;
-struct IndexedDBHostMsg_DatabaseDeleteRange_Params;
-struct IndexedDBHostMsg_DatabaseGet_Params;
-struct IndexedDBHostMsg_DatabaseGetAll_Params;
struct IndexedDBHostMsg_DatabaseObserve_Params;
-struct IndexedDBHostMsg_DatabaseOpenCursor_Params;
-struct IndexedDBHostMsg_DatabasePut_Params;
-struct IndexedDBHostMsg_DatabaseSetIndexKeys_Params;
-struct IndexedDBHostMsg_FactoryDeleteDatabase_Params;
-struct IndexedDBHostMsg_FactoryGetDatabaseNames_Params;
-struct IndexedDBHostMsg_FactoryOpen_Params;
struct IndexedDBMsg_Observation;
struct IndexedDBMsg_ObserverChanges;
@@ -49,18 +34,20 @@ class Origin;
namespace content {
class IndexedDBBlobInfo;
+class IndexedDBCallbacks;
class IndexedDBConnection;
class IndexedDBContextImpl;
class IndexedDBCursor;
+class IndexedDBDatabaseCallbacks;
class IndexedDBKey;
-class IndexedDBKeyPath;
-class IndexedDBKeyRange;
class IndexedDBObservation;
class IndexedDBObserverChanges;
-struct IndexedDBDatabaseMetadata;
// Handles all IndexedDB related messages from a particular renderer process.
-class IndexedDBDispatcherHost : public BrowserMessageFilter {
+class IndexedDBDispatcherHost
+ : public BrowserMessageFilter,
+ public BrowserAssociatedInterface<::indexed_db::mojom::Factory>,
+ public ::indexed_db::mojom::Factory {
public:
// Only call the constructor from the UI thread.
IndexedDBDispatcherHost(int ipc_process_id,
@@ -68,8 +55,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
IndexedDBContextImpl* indexed_db_context,
ChromeBlobStorageContext* blob_storage_context);
- static ::IndexedDBDatabaseMetadata ConvertMetadata(
- const content::IndexedDBDatabaseMetadata& metadata);
static IndexedDBMsg_ObserverChanges ConvertObserverChanges(
std::unique_ptr<IndexedDBObserverChanges> changes);
static IndexedDBMsg_Observation ConvertObservation(
@@ -89,16 +74,17 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
storage::BlobStorageContext* blob_storage_context() const {
return blob_storage_context_->context();
}
+ int ipc_process_id() const { return ipc_process_id_; }
// IndexedDBCallbacks call these methods to add the results into the
// applicable map. See below for more details.
int32_t Add(IndexedDBCursor* cursor);
- int32_t Add(IndexedDBConnection* connection,
- int32_t ipc_thread_id,
- const url::Origin& origin);
- void RegisterTransactionId(int64_t host_transaction_id,
+ bool RegisterTransactionId(int64_t host_transaction_id,
const url::Origin& origin);
+ bool GetTransactionSize(int64_t host_transaction_id,
+ int64_t* transaction_size);
+ void AddToTransaction(int64_t host_transaction_id, int64_t value_length);
IndexedDBCursor* GetCursorFromId(int32_t ipc_cursor_id);
@@ -114,6 +100,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
static uint32_t TransactionIdToProcessId(int64_t host_transaction_id);
std::string HoldBlobData(const IndexedDBBlobInfo& blob_info);
+ void DropBlobData(const std::string& uuid);
// True if the channel is closing/closed and outstanding requests
// can be abandoned. Only access on IndexedDB thread.
@@ -126,9 +113,8 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
// Used in nested classes.
typedef std::map<int64_t, int64_t> TransactionIDToDatabaseIDMap;
- typedef std::map<int64_t, uint64_t> TransactionIDToSizeMap;
+ typedef std::map<int64_t, int64_t> TransactionIDToSizeMap;
typedef std::map<int64_t, url::Origin> TransactionIDToOriginMap;
- typedef std::map<int32_t, url::Origin> WebIDBObjectIDToOriginMap;
// IDMap for RefCounted types
template <typename RefCountedType>
@@ -162,90 +148,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
DISALLOW_COPY_AND_ASSIGN(RefIDMap);
};
- class DatabaseDispatcherHost {
- public:
- explicit DatabaseDispatcherHost(IndexedDBDispatcherHost* parent);
- ~DatabaseDispatcherHost();
-
- void CloseAll();
- bool OnMessageReceived(const IPC::Message& message);
-
- void OnCreateObjectStore(
- const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params);
- void OnDeleteObjectStore(int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id);
- void OnRenameObjectStore(int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- const base::string16& new_name);
- void OnCreateTransaction(
- const IndexedDBHostMsg_DatabaseCreateTransaction_Params&);
- void OnClose(int32_t ipc_database_id);
- void OnVersionChangeIgnored(int32_t ipc_database_id);
- void OnDestroyed(int32_t ipc_database_id);
-
- void OnObserve(const IndexedDBHostMsg_DatabaseObserve_Params&);
- void OnUnobserve(int32_t ipc_database_id,
- const std::vector<int32_t>& observer_ids_to_remove);
-
- void OnGet(const IndexedDBHostMsg_DatabaseGet_Params& params);
- void OnGetAll(const IndexedDBHostMsg_DatabaseGetAll_Params& params);
- // OnPutWrapper starts on the IO thread so that it can grab BlobDataHandles
- // before posting to the IDB TaskRunner for the rest of the job.
- void OnPutWrapper(const IndexedDBHostMsg_DatabasePut_Params& params);
- void OnPut(const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles);
- void OnSetIndexKeys(
- const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params);
- void OnSetIndexesReady(int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- const std::vector<int64_t>& ids);
- void OnOpenCursor(const IndexedDBHostMsg_DatabaseOpenCursor_Params& params);
- void OnCount(const IndexedDBHostMsg_DatabaseCount_Params& params);
- void OnDeleteRange(
- const IndexedDBHostMsg_DatabaseDeleteRange_Params& params);
- void OnClear(int32_t ipc_thread_id,
- int32_t ipc_callbacks_id,
- int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id);
- void OnCreateIndex(
- const IndexedDBHostMsg_DatabaseCreateIndex_Params& params);
- void OnDeleteIndex(int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id);
- void OnRenameIndex(int32_t ipc_database_id,
- int64_t transaction_id,
- int64_t object_store_id,
- int64_t index_id,
- const base::string16& new_name);
-
- void OnAbort(int32_t ipc_database_id, int64_t transaction_id);
- void OnCommit(int32_t ipc_database_id, int64_t transaction_id);
- void OnGotUsageAndQuotaForCommit(int32_t ipc_database_id,
- int64_t transaction_id,
- storage::QuotaStatusCode status,
- int64_t usage,
- int64_t quota);
-
- IndexedDBDispatcherHost* parent_;
- IDMap<IndexedDBConnection, IDMapOwnPointer> map_;
- WebIDBObjectIDToOriginMap database_origin_map_;
- TransactionIDToSizeMap transaction_size_map_;
- TransactionIDToOriginMap transaction_origin_map_;
- TransactionIDToDatabaseIDMap transaction_database_map_;
-
- // Weak pointers are used when an asynchronous quota request is made, in
- // case the dispatcher is torn down before the response returns.
- base::WeakPtrFactory<DatabaseDispatcherHost> weak_factory_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DatabaseDispatcherHost);
- };
-
class CursorDispatcherHost {
public:
explicit CursorDispatcherHost(IndexedDBDispatcherHost* parent);
@@ -282,31 +184,47 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
// Helper templates.
template <class ReturnType>
- ReturnType* GetOrTerminateProcess(IDMap<ReturnType, IDMapOwnPointer>* map,
- int32_t ipc_return_object_id);
- template <class ReturnType>
ReturnType* GetOrTerminateProcess(RefIDMap<ReturnType>* map,
int32_t ipc_return_object_id);
template <typename MapType>
void DestroyObject(MapType* map, int32_t ipc_object_id);
+ // indexed_db::mojom::Factory implementation:
+ void GetDatabaseNames(
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ const url::Origin& origin) override;
+ void Open(int32_t worker_thread,
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ ::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
+ database_callbacks_info,
+ const url::Origin& origin,
+ const base::string16& name,
+ int64_t version,
+ int64_t transaction_id) override;
+ void DeleteDatabase(
+ ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info,
+ const url::Origin& origin,
+ const base::string16& name) override;
+
+ void GetDatabaseNamesOnIDBThread(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin);
+ void OpenOnIDBThread(
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
+ const url::Origin& origin,
+ const base::string16& name,
+ int64_t version,
+ int64_t transaction_id);
+ void DeleteDatabaseOnIDBThread(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::string16& name);
+
// Message processing. Most of the work is delegated to the dispatcher hosts
// below.
- void OnIDBFactoryGetDatabaseNames(
- const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& p);
- void OnIDBFactoryOpen(const IndexedDBHostMsg_FactoryOpen_Params& p);
-
- void OnIDBFactoryDeleteDatabase(
- const IndexedDBHostMsg_FactoryDeleteDatabase_Params& p);
-
void OnAckReceivedBlobs(const std::vector<std::string>& uuids);
- void OnPutHelper(
- const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles);
void ResetDispatcherHosts();
- void DropBlobData(const std::string& uuid);
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
@@ -321,7 +239,8 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
// Only access on IndexedDB thread.
bool is_open_ = true;
- std::unique_ptr<DatabaseDispatcherHost> database_dispatcher_host_;
+ TransactionIDToSizeMap transaction_size_map_;
+ TransactionIDToOriginMap transaction_origin_map_;
std::unique_ptr<CursorDispatcherHost> cursor_dispatcher_host_;
// Used to set file permissions for blob storage.
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 6d7a0a33e4e..005b40c3666 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -9,7 +9,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_simple_task_runner.h"
@@ -19,6 +18,7 @@
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "content/browser/quota/mock_quota_manager_proxy.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
@@ -81,9 +81,6 @@ class IndexedDBFactoryTest : public testing::Test {
}
protected:
- // For timers to post events.
- base::MessageLoop loop_;
-
MockIDBFactory* factory() const { return idb_factory_.get(); }
void clear_factory() { idb_factory_ = nullptr; }
IndexedDBContextImpl* context() const { return context_.get(); }
@@ -93,6 +90,8 @@ class IndexedDBFactoryTest : public testing::Test {
scoped_refptr<IndexedDBContextImpl> context_;
scoped_refptr<MockIDBFactory> idb_factory_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+ TestBrowserThreadBundle thread_bundle_;
+
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTest);
};
@@ -251,7 +250,7 @@ TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
scoped_refptr<LookingForQuotaErrorMockCallbacks> callbacks =
new LookingForQuotaErrorMockCallbacks;
scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks =
- new IndexedDBDatabaseCallbacks(nullptr, 0, 0);
+ new IndexedDBDatabaseCallbacks(nullptr, 0, nullptr);
const base::string16 name(ASCIIToUTF16("name"));
std::unique_ptr<IndexedDBPendingConnection> connection(
base::MakeUnique<IndexedDBPendingConnection>(
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
index f17364adf45..27bc4886b2b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
@@ -24,9 +24,8 @@ IndexWriter::IndexWriter(
const IndexedDBIndexMetadata& index_metadata)
: index_metadata_(index_metadata) {}
-IndexWriter::IndexWriter(
- const IndexedDBIndexMetadata& index_metadata,
- const IndexedDBDatabase::IndexKeys& index_keys)
+IndexWriter::IndexWriter(const IndexedDBIndexMetadata& index_metadata,
+ const IndexedDBIndexKeys& index_keys)
: index_metadata_(index_metadata), index_keys_(index_keys) {}
IndexWriter::~IndexWriter() {}
@@ -112,17 +111,16 @@ bool IndexWriter::AddingKeyAllowed(
return true;
}
-bool MakeIndexWriters(
- IndexedDBTransaction* transaction,
- IndexedDBBackingStore* backing_store,
- int64_t database_id,
- const IndexedDBObjectStoreMetadata& object_store,
- const IndexedDBKey& primary_key, // makes a copy
- bool key_was_generated,
- const std::vector<IndexedDBDatabase::IndexKeys>& index_keys,
- std::vector<std::unique_ptr<IndexWriter>>* index_writers,
- base::string16* error_message,
- bool* completed) {
+bool MakeIndexWriters(IndexedDBTransaction* transaction,
+ IndexedDBBackingStore* backing_store,
+ int64_t database_id,
+ const IndexedDBObjectStoreMetadata& object_store,
+ const IndexedDBKey& primary_key, // makes a copy
+ bool key_was_generated,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ std::vector<std::unique_ptr<IndexWriter>>* index_writers,
+ base::string16* error_message,
+ bool* completed) {
*completed = false;
for (const auto& it : index_keys) {
@@ -130,7 +128,7 @@ bool MakeIndexWriters(
if (found == object_store.indexes.end())
continue;
const IndexedDBIndexMetadata& index = found->second;
- IndexedDBDatabase::IndexKeys keys = it;
+ IndexedDBIndexKeys keys = it;
// If the object_store is using auto_increment, then any indexes with an
// identical key_path need to also use the primary (generated) key as a key.
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.h b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
index f4cae95b532..bf9c4e88109 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.h
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
@@ -14,8 +14,8 @@
#include "base/macros.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
namespace content {
@@ -27,7 +27,7 @@ class IndexWriter {
explicit IndexWriter(const IndexedDBIndexMetadata& index_metadata);
IndexWriter(const IndexedDBIndexMetadata& index_metadata,
- const IndexedDBDatabase::IndexKeys& index_keys);
+ const IndexedDBIndexKeys& index_keys);
bool VerifyIndexKeys(IndexedDBBackingStore* store,
IndexedDBBackingStore::Transaction* transaction,
@@ -57,22 +57,21 @@ class IndexWriter {
bool* allowed) const WARN_UNUSED_RESULT;
const IndexedDBIndexMetadata index_metadata_;
- IndexedDBDatabase::IndexKeys index_keys_;
+ IndexedDBIndexKeys index_keys_;
DISALLOW_COPY_AND_ASSIGN(IndexWriter);
};
-bool MakeIndexWriters(
- IndexedDBTransaction* transaction,
- IndexedDBBackingStore* store,
- int64_t database_id,
- const IndexedDBObjectStoreMetadata& metadata,
- const IndexedDBKey& primary_key,
- bool key_was_generated,
- const std::vector<IndexedDBDatabase::IndexKeys>& index_keys,
- std::vector<std::unique_ptr<IndexWriter>>* index_writers,
- base::string16* error_message,
- bool* completed) WARN_UNUSED_RESULT;
+bool MakeIndexWriters(IndexedDBTransaction* transaction,
+ IndexedDBBackingStore* store,
+ int64_t database_id,
+ const IndexedDBObjectStoreMetadata& metadata,
+ const IndexedDBKey& primary_key,
+ bool key_was_generated,
+ const std::vector<IndexedDBIndexKeys>& index_keys,
+ std::vector<std::unique_ptr<IndexWriter>>* index_writers,
+ base::string16* error_message,
+ bool* completed) WARN_UNUSED_RESULT;
} // namespace content
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 cb3e8b52b63..a6e0d7cbe9c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -232,8 +232,7 @@ void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
// has completed.
base::FilePath temp_path = temp_dir.Take();
- std::string origin_id =
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize()));
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin.GetURL());
base::FilePath zip_path =
temp_path.AppendASCII(origin_id).AddExtension(FILE_PATH_LITERAL("zip"));
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.cc b/chromium/content/browser/indexed_db/indexed_db_metadata.cc
deleted file mode 100644
index 899c881ad13..00000000000
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/indexed_db/indexed_db_metadata.h"
-
-namespace content {
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata() = default;
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry)
- : name(name),
- id(id),
- key_path(key_path),
- unique(unique),
- multi_entry(multi_entry) {}
-
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(
- const IndexedDBIndexMetadata& other) = default;
-
-IndexedDBIndexMetadata::~IndexedDBIndexMetadata() = default;
-
-IndexedDBIndexMetadata& IndexedDBIndexMetadata::operator=(
- const IndexedDBIndexMetadata& other) = default;
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool auto_increment,
- int64_t max_index_id)
- : name(name),
- id(id),
- key_path(key_path),
- auto_increment(auto_increment),
- max_index_id(max_index_id) {}
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata() = default;
-
-IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- const IndexedDBObjectStoreMetadata& other) = default;
-
-IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() = default;
-
-IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
- const IndexedDBObjectStoreMetadata& other) = default;
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata() : version(NO_VERSION) {}
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- const base::string16& name,
- int64_t id,
- int64_t version,
- int64_t max_object_store_id)
- : name(name),
- id(id),
- version(version),
- max_object_store_id(max_object_store_id) {}
-
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- const IndexedDBDatabaseMetadata& other) = default;
-
-IndexedDBDatabaseMetadata::~IndexedDBDatabaseMetadata() = default;
-
-IndexedDBDatabaseMetadata& IndexedDBDatabaseMetadata::operator=(
- IndexedDBDatabaseMetadata& other) = default;
-
-} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.h b/chromium/content/browser/indexed_db/indexed_db_metadata.h
deleted file mode 100644
index 9d4f0993d9b..00000000000
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
-#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
-
-#include <stdint.h>
-
-#include <map>
-
-#include "base/strings/string16.h"
-#include "content/common/indexed_db/indexed_db_key_path.h"
-
-namespace content {
-
-struct CONTENT_EXPORT IndexedDBIndexMetadata {
- static const int64_t kInvalidId = -1;
-
- IndexedDBIndexMetadata();
- IndexedDBIndexMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool unique,
- bool multi_entry);
- IndexedDBIndexMetadata(const IndexedDBIndexMetadata& other);
- ~IndexedDBIndexMetadata();
- IndexedDBIndexMetadata& operator=(const IndexedDBIndexMetadata& other);
-
- base::string16 name;
- int64_t id;
- IndexedDBKeyPath key_path;
- bool unique;
- bool multi_entry;
-};
-
-struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
-
- static const int64_t kInvalidId = -1;
-
- IndexedDBObjectStoreMetadata();
- IndexedDBObjectStoreMetadata(const base::string16& name,
- int64_t id,
- const IndexedDBKeyPath& key_path,
- bool auto_increment,
- int64_t max_index_id);
- IndexedDBObjectStoreMetadata(const IndexedDBObjectStoreMetadata& other);
- ~IndexedDBObjectStoreMetadata();
- IndexedDBObjectStoreMetadata& operator=(
- const IndexedDBObjectStoreMetadata& other);
-
- base::string16 name;
- int64_t id;
- IndexedDBKeyPath key_path;
- bool auto_increment;
- int64_t max_index_id;
-
- std::map<int64_t, IndexedDBIndexMetadata> indexes;
-};
-
-struct CONTENT_EXPORT IndexedDBDatabaseMetadata {
- // TODO(jsbell): These can probably be collapsed into 0.
- enum { NO_VERSION = -1, DEFAULT_VERSION = 0 };
-
- IndexedDBDatabaseMetadata();
- IndexedDBDatabaseMetadata(const base::string16& name,
- int64_t id,
- int64_t version,
- int64_t max_object_store_id);
- IndexedDBDatabaseMetadata(const IndexedDBDatabaseMetadata& other);
- ~IndexedDBDatabaseMetadata();
- IndexedDBDatabaseMetadata& operator=(IndexedDBDatabaseMetadata& other);
-
- base::string16 name;
- int64_t id;
- int64_t version;
- int64_t max_object_store_id;
-
- std::map<int64_t, IndexedDBObjectStoreMetadata> object_stores;
-};
-} // namespace content
-
-#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_METADATA_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
index 05eaf36b481..894d36127cf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -13,6 +13,7 @@
#include "content/public/browser/browser_thread.h"
#include "net/base/url_util.h"
#include "storage/browser/database/database_util.h"
+#include "url/origin.h"
using storage::QuotaClient;
using storage::DatabaseUtil;
@@ -37,7 +38,7 @@ void GetAllOriginsOnIndexedDBThread(IndexedDBContextImpl* context,
std::set<GURL>* origins_to_return) {
DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
for (const auto& origin : context->GetAllOrigins())
- origins_to_return->insert(GURL(origin.Serialize()));
+ origins_to_return->insert(origin.GetURL());
}
void DidGetOrigins(const IndexedDBQuotaClient::GetOriginsCallback& callback,
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.h b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
index 87246383dc2..bc96cefa098 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.h
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
@@ -15,6 +15,7 @@
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_task.h"
#include "storage/common/quota/quota_types.h"
+#include "url/gurl.h"
namespace content {
class IndexedDBContextImpl;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index 0308cbb4536..bcd30a2e29f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
@@ -17,6 +16,7 @@
#include "content/browser/indexed_db/indexed_db_observer.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_factory.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -69,8 +69,8 @@ class IndexedDBTransactionTest : public testing::Test {
scoped_refptr<IndexedDBDatabase> db_;
private:
- base::MessageLoop message_loop_;
scoped_refptr<MockIndexedDBFactory> factory_;
+ TestBrowserThreadBundle thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index 63e1aaa14e6..284f7575f87 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -11,7 +11,6 @@
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_factory_impl.h"
@@ -22,6 +21,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -41,11 +41,8 @@ class IndexedDBTest : public testing::Test {
kSessionOnlyOrigin(GURL("http://session-only/")),
task_runner_(new base::TestSimpleTaskRunner),
special_storage_policy_(new MockSpecialStoragePolicy),
- quota_manager_proxy_(new MockQuotaManagerProxy(nullptr, nullptr)),
- file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_) {
- special_storage_policy_->AddSessionOnly(
- GURL(kSessionOnlyOrigin.Serialize()));
+ quota_manager_proxy_(new MockQuotaManagerProxy(nullptr, nullptr)) {
+ special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin.GetURL());
}
~IndexedDBTest() override {
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
@@ -54,14 +51,12 @@ class IndexedDBTest : public testing::Test {
protected:
void FlushIndexedDBTaskRunner() { task_runner_->RunUntilIdle(); }
- base::MessageLoopForIO message_loop_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
private:
- BrowserThreadImpl file_thread_;
- BrowserThreadImpl io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBTest);
};
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
index dbb75651b24..1125bdecb3b 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
@@ -9,7 +9,7 @@
namespace content {
MockIndexedDBDatabaseCallbacks::MockIndexedDBDatabaseCallbacks()
- : IndexedDBDatabaseCallbacks(NULL, 0, 0),
+ : IndexedDBDatabaseCallbacks(nullptr, 0, nullptr),
abort_called_(false),
forced_close_called_(false) {}
diff --git a/chromium/content/browser/loader/DEPS b/chromium/content/browser/loader/DEPS
index 1245eec0631..b655be17bdb 100644
--- a/chromium/content/browser/loader/DEPS
+++ b/chromium/content/browser/loader/DEPS
@@ -19,11 +19,11 @@ specific_include_rules = {
"+content/browser/loader/resource_message_filter.h",
"+content/browser/loader/resource_request_info_impl.h",
"+content/common/content_export.h",
+ "+content/public/browser/resource_controller.h",
"+content/public/browser/resource_dispatcher_host_delegate.h",
"+content/public/common/resource_response.h",
# TODO: these all have to be removed.
- "+content/browser/host_zoom_map_impl.h",
"+content/public/common/content_features.h",
# TODO: To be replaced by mojo.
@@ -88,6 +88,8 @@ specific_include_rules = {
"+content/browser/loader/resource_request_info_impl.h",
"+content/common/content_export.h",
"+content/common/resource_request_completion_status.h",
+ "+content/public/browser/global_request_id.h",
+ "+content/public/browser/resource_controller.h",
"+content/public/browser/resource_dispatcher_host_delegate.h",
"+content/public/common/resource_response.h",
"+content/common/url_loader.mojom.h",
@@ -177,6 +179,7 @@ specific_include_rules = {
"+content/browser/resource_context_impl.h",
"+content/browser/service_worker/foreign_fetch_request_handler.h",
"+content/browser/service_worker/link_header_support.h",
+ "+content/browser/service_worker/service_worker_navigation_handle_core.h",
"+content/browser/service_worker/service_worker_request_handler.h",
"+content/browser/streams/stream.h",
"+content/browser/streams/stream_context.h",
@@ -222,6 +225,7 @@ specific_include_rules = {
"+content/common/content_export.h",
"+content/public/browser/resource_controller.h",
"+content/public/browser/resource_dispatcher_host_login_delegate.h",
+ "+content/public/common/browser_side_navigation_policy.h",
"+content/public/common/resource_response.h",
"+content/public/common/resource_type.h",
@@ -255,6 +259,7 @@ specific_include_rules = {
# TODO: these all have to be removed.
"+content/browser/frame_host/frame_tree_node.h",
+ "+content/browser/service_worker/service_worker_context_wrapper.h",
"+content/browser/web_contents/web_contents_impl.h",
"+content/common/net/url_request_service_worker_data.h",
"+content/common/net/url_request_user_data.h",
@@ -306,6 +311,7 @@ specific_include_rules = {
"+content/browser/loader/test_url_loader_client.h",
"+content/common/resource_request_completion_status.h",
"+content/common/url_loader.mojom.h",
+ "+content/common/url_loader_factory.mojom.h",
"+content/public/common/resource_response.h",
],
"url_loader_factory_impl\.(cc|h)": [
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index 75d9289257d..69df9938434 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/host_zoom_map_impl.h"
#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_buffer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -26,6 +25,7 @@
#include "content/common/resource_messages.h"
#include "content/common/resource_request_completion_status.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_response.h"
@@ -351,21 +351,6 @@ bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->raw_header_size();
- const HostZoomMapImpl* host_zoom_map =
- static_cast<const HostZoomMapImpl*>(info->filter()->GetHostZoomMap());
-
- if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME && host_zoom_map) {
- const GURL& request_url = request()->url();
- int render_process_id = info->GetChildID();
- int render_view_id = info->GetRouteID();
-
- double zoom_level = host_zoom_map->GetZoomLevelForView(
- request_url, render_process_id, render_view_id);
-
- info->filter()->Send(new ViewMsg_SetZoomLevelForLoadingURL(
- render_view_id, request_url, zoom_level));
- }
-
// If the parent handler downloaded the resource to a file, grant the child
// read permissions on it.
if (!response->head.download_file_path.empty()) {
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index 023e262842d..c02a38c34aa 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -24,10 +24,7 @@ class URLRequest;
namespace content {
class ResourceBuffer;
-class ResourceContext;
class ResourceDispatcherHostImpl;
-class ResourceMessageFilter;
-class SharedIOBuffer;
// Used to complete an asynchronous resource request in response to resource
// load events from the resource dispatcher host.
diff --git a/chromium/content/browser/loader/async_resource_handler_browsertest.cc b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
index d0e15f0bdb5..e1bc8fe68ab 100644
--- a/chromium/content/browser/loader/async_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
@@ -69,9 +69,9 @@ class AsyncResourceHandlerBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) {
net::EmbeddedTestServer* test_server = embedded_test_server();
- ASSERT_TRUE(test_server->Start());
test_server->RegisterRequestHandler(
base::Bind(&HandlePostAndRedirectURLs, kPostPath));
+ ASSERT_TRUE(test_server->Start());
NavigateToURL(shell(),
test_server->GetURL("/loader/async_resource_handler.html"));
@@ -87,9 +87,9 @@ IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) {
IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest,
UploadProgressRedirect) {
net::EmbeddedTestServer* test_server = embedded_test_server();
- ASSERT_TRUE(test_server->Start());
test_server->RegisterRequestHandler(
base::Bind(&HandlePostAndRedirectURLs, kRedirectPostPath));
+ ASSERT_TRUE(test_server->Start());
NavigateToURL(shell(),
test_server->GetURL("/loader/async_resource_handler.html"));
diff --git a/chromium/content/browser/loader/async_resource_handler_unittest.cc b/chromium/content/browser/loader/async_resource_handler_unittest.cc
index 9764dfdc9b6..9662afd54b7 100644
--- a/chromium/content/browser/loader/async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/async_resource_handler_unittest.cc
@@ -14,7 +14,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/feature_list.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
@@ -23,6 +22,7 @@
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_loader_delegate.h"
@@ -97,7 +97,6 @@ class RecordingResourceMessageFilter : public ResourceMessageFilter {
nullptr,
nullptr,
nullptr,
- nullptr,
base::Bind(&RecordingResourceMessageFilter::GetContexts,
base::Unretained(this))),
resource_context_(resource_context),
@@ -143,6 +142,8 @@ class AsyncResourceHandlerTest : public ::testing::Test,
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {}
void TearDown() override {
+ if (filter_)
+ filter_->OnChannelClosing();
// Prevent memory leaks.
filter_ = nullptr;
rdh_.Shutdown();
@@ -263,11 +264,9 @@ TEST_F(AsyncResourceHandlerTest, OneChunkLengths) {
TEST_F(AsyncResourceHandlerTest, InlinedChunkLengths) {
// TODO(ricea): Remove this Feature-enabling code once the feature is on by
// default.
- auto feature_list = base::MakeUnique<base::FeatureList>();
- feature_list->InitializeFromCommandLine(
- features::kOptimizeLoadingIPCForSmallResources.name, "");
- base::FeatureList::ClearInstanceForTesting();
- base::FeatureList::SetInstance(std::move(feature_list));
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kOptimizeLoadingIPCForSmallResources);
// Smaller than kInlinedLeadingChunkSize.
StartRequestAndWaitWithResponseDataSize(8);
diff --git a/chromium/content/browser/loader/async_revalidation_driver.h b/chromium/content/browser/loader/async_revalidation_driver.h
index babd3f78e9d..a5bf1ec7c4e 100644
--- a/chromium/content/browser/loader/async_revalidation_driver.h
+++ b/chromium/content/browser/loader/async_revalidation_driver.h
@@ -19,10 +19,6 @@
#include "net/base/io_buffer.h"
#include "net/url_request/url_request.h"
-namespace net {
-class HttpCache;
-}
-
namespace content {
// This class is responsible for driving the URLRequest for an async
diff --git a/chromium/content/browser/loader/async_revalidation_manager.cc b/chromium/content/browser/loader/async_revalidation_manager.cc
index 53279fe1320..abdf659fd22 100644
--- a/chromium/content/browser/loader/async_revalidation_manager.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager.cc
@@ -109,7 +109,7 @@ void AsyncRevalidationManager::BeginAsyncRevalidation(
// Construct the request.
std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest(
- for_request.url(), net::MINIMUM_PRIORITY, nullptr);
+ for_request.url(), net::IDLE, nullptr);
new_request->set_method(for_request.method());
new_request->set_first_party_for_cookies(
@@ -169,7 +169,7 @@ bool AsyncRevalidationManager::QualifiesForAsyncRevalidation(
const ResourceRequest& request) {
if (request.load_flags &
(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
- net::LOAD_VALIDATE_CACHE | net::LOAD_PREFERRING_CACHE |
+ net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
net::LOAD_ONLY_FROM_CACHE | net::LOAD_IGNORE_LIMITS |
net::LOAD_PREFETCH)) {
return false;
diff --git a/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
index f02e6fca294..2646222c750 100644
--- a/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
@@ -8,14 +8,15 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/feature_list.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -43,20 +44,10 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
~AsyncRevalidationManagerBrowserTest() override {}
void SetUp() override {
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- "StaleWhileRevalidate2", std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
-
- ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ scoped_feature_list_.InitAndEnableFeature(features::kStaleWhileRevalidate);
ContentBrowserTest::SetUp();
}
- void SetUpOnMainThread() override {
- embedded_test_server()->StartAcceptingConnections();
- }
-
base::RunLoop* run_loop() { return &run_loop_; }
int requests_counted() const { return requests_counted_; }
@@ -151,6 +142,7 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
base::RunLoop run_loop_;
int requests_counted_ = 0;
+ base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(AsyncRevalidationManagerBrowserTest);
};
@@ -159,11 +151,13 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
// triggers an async revalidation.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
StaleWhileRevalidateIsApplied) {
+ RegisterCountingRequestHandler();
+ ASSERT_TRUE(embedded_test_server()->Start());
+
// PlzNavigate: Stale while revalidate is disabled.
// TODO(clamy): Re-enable the test when there is support.
if (IsBrowserSideNavigationEnabled())
return;
- RegisterCountingRequestHandler();
GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
EXPECT_TRUE(TitleBecomes(url, "Version 1"));
@@ -186,12 +180,14 @@ IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
// The fresh cache entry must become visible once the async revalidation request
// has been sent.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest, CacheIsUpdated) {
+ RegisterCountingRequestHandler();
+ ASSERT_TRUE(embedded_test_server()->Start());
+
// PlzNavigate: Stale while revalidate is disabled.
// TODO(clamy): Re-enable the test when there is support.
if (IsBrowserSideNavigationEnabled())
return;
using base::ASCIIToUTF16;
- RegisterCountingRequestHandler();
GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
EXPECT_TRUE(TitleBecomes(url, "Version 1"));
@@ -218,11 +214,13 @@ IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest, CacheIsUpdated) {
// applied immediately.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
CookieSetAsynchronously) {
+ RegisterCookieRequestHandler();
+ ASSERT_TRUE(embedded_test_server()->Start());
+
// PlzNavigate: Stale while revalidate is disabled.
// TODO(clamy): Re-enable the test when there is support.
if (IsBrowserSideNavigationEnabled())
return;
- RegisterCookieRequestHandler();
GURL url(embedded_test_server()->GetURL(kCookieHtmlPath));
// Set cookie to version=1
diff --git a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
index 392760d5690..b06f63ce168 100644
--- a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
@@ -212,7 +212,6 @@ class BlackholeFilter : public ResourceMessageFilter {
nullptr,
nullptr,
nullptr,
- nullptr,
base::Bind(&BlackholeFilter::GetContexts, base::Unretained(this))),
resource_context_(resource_context) {
ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
@@ -248,6 +247,7 @@ ResourceRequest CreateResourceRequest(const char* method,
request.method = std::string(method);
request.url = url;
request.first_party_for_cookies = url; // Bypass third-party cookie blocking.
+ request.request_initiator = url::Origin(url); // Ensure initiator is set.
request.referrer_policy = blink::WebReferrerPolicyDefault;
request.load_flags = 0;
request.origin_pid = 0;
@@ -289,6 +289,7 @@ class AsyncRevalidationManagerTest : public ::testing::Test {
base::WrapUnique(new net::TestNetworkDelegate)) {}
void TearDown() override {
+ filter_->OnChannelClosing();
host_.CancelRequestsForProcess(filter_->child_id());
host_.Shutdown();
host_.CancelRequestsForContext(browser_context_->GetResourceContext());
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.cc b/chromium/content/browser/loader/cross_site_resource_handler.cc
deleted file mode 100644
index ecffa2095fc..00000000000
--- a/chromium/content/browser/loader/cross_site_resource_handler.cc
+++ /dev/null
@@ -1,388 +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/cross_site_resource_handler.h"
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "content/browser/appcache/appcache_interceptor.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/site_isolation_policy.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/resource_controller.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/resource_response.h"
-#include "content/public/common/url_constants.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-namespace {
-
-bool leak_requests_for_testing_ = false;
-
-// The parameters to OnCrossSiteResponseHelper exceed the number of arguments
-// base::Bind supports.
-struct CrossSiteResponseParams {
- CrossSiteResponseParams(
- int render_frame_id,
- const GlobalRequestID& global_request_id,
- const std::vector<GURL>& transfer_url_chain,
- const Referrer& referrer,
- ui::PageTransition page_transition,
- bool should_replace_current_entry)
- : render_frame_id(render_frame_id),
- global_request_id(global_request_id),
- transfer_url_chain(transfer_url_chain),
- referrer(referrer),
- page_transition(page_transition),
- should_replace_current_entry(should_replace_current_entry) {
- }
-
- int render_frame_id;
- GlobalRequestID global_request_id;
- std::vector<GURL> transfer_url_chain;
- Referrer referrer;
- ui::PageTransition page_transition;
- bool should_replace_current_entry;
-};
-
-void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
- std::unique_ptr<CrossSiteTransferringRequest> cross_site_transferring_request(
- new CrossSiteTransferringRequest(params.global_request_id));
-
- RenderFrameHostImpl* rfh =
- RenderFrameHostImpl::FromID(params.global_request_id.child_id,
- params.render_frame_id);
- if (rfh && rfh->is_active()) {
- if (rfh->GetParent()) {
- // We should only swap processes for subframes in --site-per-process mode.
- // CrossSiteResourceHandler is not installed on subframe requests in
- // default Chrome.
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
- }
- rfh->OnCrossSiteResponse(
- params.global_request_id, std::move(cross_site_transferring_request),
- params.transfer_url_chain, params.referrer, params.page_transition,
- params.should_replace_current_entry);
- } else if (leak_requests_for_testing_) {
- // Some unit tests expect requests to be leaked in this case, so they can
- // pass them along manually.
- cross_site_transferring_request->ReleaseRequest();
- }
-}
-
-// Returns whether a transfer is needed by doing a check on the UI thread.
-CrossSiteResourceHandler::NavigationDecision
-CheckNavigationPolicyOnUI(GURL real_url, int process_id, int render_frame_id) {
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
- RenderFrameHostImpl* rfh =
- RenderFrameHostImpl::FromID(process_id, render_frame_id);
-
- // Without a valid RFH against which to check, we must cancel the request,
- // to prevent the resource at |url| from being delivered to a potentially
- // unsuitable renderer process.
- if (!rfh || !rfh->is_active())
- return CrossSiteResourceHandler::NavigationDecision::CANCEL_REQUEST;
-
- RenderFrameHostManager* manager = rfh->frame_tree_node()->render_manager();
- if (manager->IsRendererTransferNeededForNavigation(rfh, real_url))
- return CrossSiteResourceHandler::NavigationDecision::TRANSFER_REQUIRED;
- else
- return CrossSiteResourceHandler::NavigationDecision::USE_EXISTING_RENDERER;
-}
-
-} // namespace
-
-CrossSiteResourceHandler::CrossSiteResourceHandler(
- std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request)
- : LayeredResourceHandler(request, std::move(next_handler)),
- has_started_response_(false),
- in_cross_site_transition_(false),
- completed_during_transition_(false),
- did_defer_(false),
- weak_ptr_factory_(this) {}
-
-CrossSiteResourceHandler::~CrossSiteResourceHandler() {
- // Cleanup back-pointer stored on the request info.
- GetRequestInfo()->set_cross_site_handler(NULL);
-}
-
-bool CrossSiteResourceHandler::OnRequestRedirected(
- const net::RedirectInfo& redirect_info,
- ResourceResponse* response,
- bool* defer) {
- // We should not have started the transition before being redirected.
- DCHECK(!in_cross_site_transition_);
- return next_handler_->OnRequestRedirected(redirect_info, response, defer);
-}
-
-bool CrossSiteResourceHandler::OnResponseStarted(
- ResourceResponse* response,
- bool* defer) {
- response_ = response;
- has_started_response_ = true;
-
- // Store this handler on the ExtraRequestInfo, so that RDH can call our
- // ResumeResponse method when we are ready to resume.
- ResourceRequestInfoImpl* info = GetRequestInfo();
- info->set_cross_site_handler(this);
-
- return OnNormalResponseStarted(response, defer);
-}
-
-bool CrossSiteResourceHandler::OnNormalResponseStarted(
- ResourceResponse* response,
- bool* defer) {
- // At this point, we know that the response is safe to send back to the
- // renderer: it is not a download, and it has passed the SSL and safe
- // browsing checks.
- // We should not have already started the transition before now.
- DCHECK(!in_cross_site_transition_);
-
- ResourceRequestInfoImpl* info = GetRequestInfo();
-
- // The content embedder can decide that a transfer to a different process is
- // required for this URL. If so, pause the response now. Other cross process
- // navigations can proceed immediately, since we run the unload handler at
- // commit time. Note that a process swap may no longer be necessary if we
- // transferred back into the original process due to a redirect.
- bool definitely_transfer =
- GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
- info->GetContext(), request()->original_url(), request()->url());
-
- // If this is a download, just pass the response through without doing a
- // cross-site check. The renderer will see it is a download and abort the
- // request.
- //
- // Similarly, HTTP 204 (No Content) responses leave us showing the previous
- // page. We should allow the navigation to finish without running the unload
- // handler or swapping in the pending RenderFrameHost.
- //
- // In both cases, any pending RenderFrameHost (if one was created for this
- // navigation) will stick around until the next cross-site navigation, since
- // we are unable to tell when to destroy it.
- // See RenderFrameHostManager::RendererAbortedProvisionalLoad.
- //
- // TODO(davidben): Unify IsDownload() and is_stream(). Several places need to
- // check for both and remembering about streams is error-prone.
- if (info->IsDownload() || info->is_stream() ||
- (response->head.headers.get() &&
- response->head.headers->response_code() == 204)) {
- return next_handler_->OnResponseStarted(response, defer);
- }
-
- if (definitely_transfer) {
- // Now that we know a transfer is needed and we have something to commit, we
- // pause to let the UI thread set up the transfer.
- StartCrossSiteTransition(response);
-
- // Defer loading until after the new renderer process has issued a
- // corresponding request.
- *defer = true;
- OnDidDefer();
- return true;
- }
-
- // In the site-per-process model, we may also decide (independently from the
- // content embedder's ShouldSwapProcessesForRedirect decision above) that a
- // process transfer is needed. For that we need to consult the navigation
- // policy on the UI thread, so pause the response. 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(
- info->GetChildID())) {
- return DeferForNavigationPolicyCheck(info, response, defer);
- }
-
- // No deferral needed. Pass the response through.
- return next_handler_->OnResponseStarted(response, defer);
-}
-
-void CrossSiteResourceHandler::ResumeOrTransfer(NavigationDecision decision) {
- switch (decision) {
- case NavigationDecision::CANCEL_REQUEST:
- // TODO(nick): What kind of cleanup do we need here?
- controller()->Cancel();
- break;
- case NavigationDecision::USE_EXISTING_RENDERER:
- ResumeResponse();
- break;
- case NavigationDecision::TRANSFER_REQUIRED:
- StartCrossSiteTransition(response_.get());
- break;
- }
-}
-
-bool CrossSiteResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
- CHECK(!in_cross_site_transition_);
- return next_handler_->OnReadCompleted(bytes_read, defer);
-}
-
-void CrossSiteResourceHandler::OnResponseCompleted(
- const net::URLRequestStatus& status,
- bool* defer) {
- if (!in_cross_site_transition_) {
- // If we're not transferring, then we should pass this through.
- next_handler_->OnResponseCompleted(status, defer);
- return;
- }
-
- // We have to buffer the call until after the transition completes.
- completed_during_transition_ = true;
- completed_status_ = status;
-
- // Defer to tell RDH not to notify the world or clean up the pending request.
- // We will do so in ResumeResponse.
- *defer = true;
- OnDidDefer();
-}
-
-// We can now send the response to the new renderer, which will cause
-// WebContentsImpl to swap in the new renderer and destroy the old one.
-void CrossSiteResourceHandler::ResumeResponse() {
- TRACE_EVENT_ASYNC_END0(
- "navigation", "CrossSiteResourceHandler transition", this);
- DCHECK(request());
- in_cross_site_transition_ = false;
- ResourceRequestInfoImpl* info = GetRequestInfo();
-
- if (has_started_response_) {
- // Send OnResponseStarted to the new renderer.
- DCHECK(response_.get());
- bool defer = false;
- if (!next_handler_->OnResponseStarted(response_.get(), &defer)) {
- controller()->Cancel();
- } else if (!defer) {
- // Unpause the request to resume reading. Any further reads will be
- // directed toward the new renderer.
- ResumeIfDeferred();
- }
- }
-
- // Remove ourselves from the ExtraRequestInfo.
- info->set_cross_site_handler(NULL);
-
- // If the response completed during the transition, notify the next
- // event handler.
- if (completed_during_transition_) {
- bool defer = false;
- next_handler_->OnResponseCompleted(completed_status_,
- &defer);
- if (!defer)
- ResumeIfDeferred();
- }
-}
-
-// static
-void CrossSiteResourceHandler::SetLeakRequestsForTesting(
- bool leak_requests_for_testing) {
- leak_requests_for_testing_ = leak_requests_for_testing;
-}
-
-// Prepare to transfer the response to a new RenderFrameHost.
-void CrossSiteResourceHandler::StartCrossSiteTransition(
- ResourceResponse* response) {
- TRACE_EVENT_ASYNC_BEGIN0(
- "navigation", "CrossSiteResourceHandler transition", this);
- in_cross_site_transition_ = true;
- response_ = response;
-
- // Store this handler on the ExtraRequestInfo, so that RDH can call our
- // ResumeResponse method when we are ready to resume.
- ResourceRequestInfoImpl* info = GetRequestInfo();
- info->set_cross_site_handler(this);
-
- GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
-
- // Tell the contents responsible for this request that a cross-site response
- // is starting, so that it can tell its old renderer to run its onunload
- // handler now. We will wait until the unload is finished and (if a transfer
- // is needed) for the new renderer's request to arrive.
- // The |transfer_url_chain| contains any redirect URLs that have already
- // occurred, plus the destination URL at the end.
- std::vector<GURL> transfer_url_chain;
- Referrer referrer;
- int render_frame_id = info->GetRenderFrameID();
- transfer_url_chain = request()->url_chain();
- referrer = Referrer(GURL(request()->referrer()), info->GetReferrerPolicy());
- ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id,
- response_);
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &OnCrossSiteResponseHelper,
- CrossSiteResponseParams(render_frame_id,
- global_id,
- transfer_url_chain,
- referrer,
- info->GetPageTransition(),
- info->should_replace_current_entry())));
-}
-
-bool CrossSiteResourceHandler::DeferForNavigationPolicyCheck(
- ResourceRequestInfoImpl* info,
- ResourceResponse* response,
- bool* defer) {
- // Store the response_ object internally, since the navigation is deferred
- // regardless of whether it will be a transfer or not.
- response_ = response;
-
- // Always defer the navigation to the UI thread to make a policy decision.
- // It will send the result back to the IO thread to either resume or
- // transfer it to a new renderer.
- // TODO(nasko): If the UI thread result is that transfer is required, the
- // IO thread will defer to the UI thread again through
- // StartCrossSiteTransition. This is unnecessary and the policy check on the
- // UI thread should be refactored to avoid the extra hop.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&CheckNavigationPolicyOnUI,
- request()->url(),
- info->GetChildID(),
- info->GetRenderFrameID()),
- base::Bind(&CrossSiteResourceHandler::ResumeOrTransfer,
- weak_ptr_factory_.GetWeakPtr()));
-
- // Defer loading until it is known whether the navigation will transfer
- // to a new process or continue in the existing one.
- *defer = true;
- OnDidDefer();
- return true;
-}
-
-void CrossSiteResourceHandler::ResumeIfDeferred() {
- if (did_defer_) {
- request()->LogUnblocked();
- did_defer_ = false;
- controller()->Resume();
- }
-}
-
-void CrossSiteResourceHandler::OnDidDefer() {
- did_defer_ = true;
- request()->LogBlockedBy("CrossSiteResourceHandler");
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.h b/chromium/content/browser/loader/cross_site_resource_handler.h
deleted file mode 100644
index 9030468841b..00000000000
--- a/chromium/content/browser/loader/cross_site_resource_handler.h
+++ /dev/null
@@ -1,97 +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_CROSS_SITE_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/loader/layered_resource_handler.h"
-#include "content/common/content_export.h"
-#include "net/url_request/url_request_status.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-struct TransitionLayerData;
-
-// Ensures that responses are delayed for navigations that must be transferred
-// to a different process. This handler wraps an AsyncEventHandler, and it sits
-// inside SafeBrowsing and Buffered event handlers. This is important, so that
-// it can intercept OnResponseStarted after we determine that a response is safe
-// and not a download.
-class CrossSiteResourceHandler : public LayeredResourceHandler {
- public:
- enum class NavigationDecision {
- TRANSFER_REQUIRED,
- USE_EXISTING_RENDERER,
- CANCEL_REQUEST
- };
-
- CrossSiteResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request);
- ~CrossSiteResourceHandler() override;
-
- // ResourceHandler implementation:
- bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
- ResourceResponse* response,
- bool* defer) override;
- bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
- bool OnReadCompleted(int bytes_read, bool* defer) override;
- void OnResponseCompleted(const net::URLRequestStatus& status,
- bool* defer) override;
-
- // We can now send the response to the new renderer, which will cause
- // WebContentsImpl to swap in the new renderer and destroy the old one.
- void ResumeResponse();
-
- // When set to true, requests are leaked when they can't be passed to a
- // RenderViewHost, for unit tests.
- CONTENT_EXPORT static void SetLeakRequestsForTesting(
- bool leak_requests_for_testing);
-
- private:
- // Prepare to transfer the cross-site response to a new RenderFrameHost, by
- // asking it to issue an identical request (on the UI thread).
- void StartCrossSiteTransition(ResourceResponse* response);
-
- // Defer the navigation to the UI thread to check whether transfer is required
- // or not. Currently only used in --site-per-process.
- bool DeferForNavigationPolicyCheck(ResourceRequestInfoImpl* info,
- ResourceResponse* response,
- bool* defer);
-
- bool OnNormalResponseStarted(ResourceResponse* response,
- bool* defer);
-
- void ResumeOrTransfer(NavigationDecision decision);
- void ResumeIfDeferred();
-
- // Called when about to defer a request. Sets |did_defer_| and logs the
- // defferral
- void OnDidDefer();
-
- bool has_started_response_;
- bool in_cross_site_transition_;
- bool completed_during_transition_;
- bool did_defer_;
- net::URLRequestStatus completed_status_;
- scoped_refptr<ResourceResponse> response_;
-
- // TODO(nasko): WeakPtr is needed in --site-per-process, since all navigations
- // are deferred to the UI thread and come back to IO thread via
- // PostTaskAndReplyWithResult. If a transfer is needed, it goes back to the UI
- // thread. This can be removed once the code is changed to only do one hop.
- base::WeakPtrFactory<CrossSiteResourceHandler> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CrossSiteResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
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 d245cca7cfa..cfa809fb83a 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
+#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
@@ -193,8 +194,8 @@ class CrossSiteResourceHandlerTest : public ContentBrowserTest {
&CrossSiteResourceHandlerTest::InjectResourceDispatcherHostDelegate,
base::Unretained(this)));
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
void TearDownOnMainThread() override {
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.cc b/chromium/content/browser/loader/intercepting_resource_handler.cc
index 08907205397..7c8f4a99864 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler.cc
@@ -8,71 +8,58 @@
#include "base/strings/string_util.h"
#include "content/public/common/resource_response.h"
#include "net/base/io_buffer.h"
+#include "net/url_request/url_request.h"
namespace content {
InterceptingResourceHandler::InterceptingResourceHandler(
std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request)
- : LayeredResourceHandler(request, std::move(next_handler)),
- state_(State::STARTING),
- first_read_buffer_size_(0) {}
+ : LayeredResourceHandler(request, std::move(next_handler)) {
+ next_handler_->SetController(this);
+}
InterceptingResourceHandler::~InterceptingResourceHandler() {}
+void InterceptingResourceHandler::SetController(
+ ResourceController* controller) {
+ if (state_ == State::PASS_THROUGH)
+ return LayeredResourceHandler::SetController(controller);
+ ResourceHandler::SetController(controller);
+}
+
bool InterceptingResourceHandler::OnResponseStarted(ResourceResponse* response,
bool* defer) {
// If there's no need to switch handlers, just start acting as a blind
// pass-through ResourceHandler.
if (!new_handler_) {
- state_ = State::DONE;
- first_read_buffer_ = nullptr;
+ state_ = State::PASS_THROUGH;
+ next_handler_->SetController(controller());
return next_handler_->OnResponseStarted(response, defer);
}
+ DCHECK_EQ(state_, State::STARTING);
// Otherwise, switch handlers. First, inform the original ResourceHandler
// that this will be handled entirely by the new ResourceHandler.
- // TODO(clamy): We will probably need to check the return values of these for
- // PlzNavigate.
bool defer_ignored = false;
- next_handler_->OnResponseStarted(response, &defer_ignored);
+ if (!next_handler_->OnResponseStarted(response, &defer_ignored))
+ return false;
// Although deferring OnResponseStarted is legal, the only downstream handler
// which does so is CrossSiteResourceHandler. Cross-site transitions should
// not trigger when switching handlers.
DCHECK(!defer_ignored);
- // Make a copy of the data in the first read buffer. Despite not having been
- // informed of any data being stored in first_read_buffer_, the
- // MimeSniffingResourceHandler has read the data, it's just holding it back.
- // This data should be passed to the alternate ResourceHandler and not to to
- // the current ResourceHandler.
- // TODO(clamy): see if doing the copy should be moved to the
- // MimeSniffingResourceHandler.
- if (first_read_buffer_) {
- first_read_buffer_copy_ = new net::IOBuffer(first_read_buffer_size_);
- memcpy(first_read_buffer_copy_->data(), first_read_buffer_->data(),
- first_read_buffer_size_);
- }
-
- // Send the payload to the old handler.
- SendPayloadToOldHandler();
- first_read_buffer_ = nullptr;
-
- // The original ResourceHandler is now no longer needed, so replace it with
- // the new one, before sending the response to the new one.
- next_handler_ = std::move(new_handler_);
-
- state_ =
- first_read_buffer_copy_ ? State::WAITING_FOR_BUFFER_COPY : State::DONE;
-
- return next_handler_->OnResponseStarted(response, defer);
+ // TODO(yhirano): Retaining ownership from a raw pointer is bad.
+ response_ = response;
+ state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER;
+ return DoLoop(defer);
}
bool InterceptingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
- if (state_ == State::DONE)
+ if (state_ == State::PASS_THROUGH)
return next_handler_->OnWillRead(buf, buf_size, min_size);
DCHECK_EQ(State::STARTING, state_);
@@ -83,81 +70,213 @@ bool InterceptingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
first_read_buffer_ = *buf;
first_read_buffer_size_ = *buf_size;
+ first_read_buffer_double_ = new net::IOBuffer(static_cast<size_t>(*buf_size));
+ *buf = first_read_buffer_double_;
return true;
}
bool InterceptingResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
- DCHECK(bytes_read >= 0);
- if (state_ == State::DONE)
+ DCHECK_GE(bytes_read, 0);
+ if (state_ == State::PASS_THROUGH) {
+ if (first_read_buffer_double_) {
+ // |first_read_buffer_double_| was allocated and the user wrote data to
+ // the buffer, but switching has not been done after all.
+ memcpy(first_read_buffer_->data(), first_read_buffer_double_->data(),
+ bytes_read);
+ first_read_buffer_ = nullptr;
+ first_read_buffer_double_ = nullptr;
+ }
return next_handler_->OnReadCompleted(bytes_read, defer);
+ }
- DCHECK_EQ(State::WAITING_FOR_BUFFER_COPY, state_);
- state_ = State::DONE;
+ DCHECK_EQ(State::WAITING_FOR_ON_READ_COMPLETED, state_);
+ first_read_buffer_bytes_read_ = bytes_read;
+ state_ = State::SENDING_BUFFER_TO_NEW_HANDLER;
+ return DoLoop(defer);
+}
- // Copy the data from the first read to the new ResourceHandler.
- scoped_refptr<net::IOBuffer> buf;
- int buf_len = 0;
- if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read))
- return false;
+void InterceptingResourceHandler::OnResponseCompleted(
+ const net::URLRequestStatus& status,
+ bool* defer) {
+ if (state_ == State::PASS_THROUGH) {
+ LayeredResourceHandler::OnResponseCompleted(status, defer);
+ return;
+ }
+ if (!new_handler_) {
+ // Therer is only one ResourceHandler in this InterceptingResourceHandler.
+ state_ = State::PASS_THROUGH;
+ first_read_buffer_double_ = nullptr;
+ next_handler_->SetController(controller());
+ next_handler_->OnResponseCompleted(status, defer);
+ return;
+ }
- CHECK(buf_len >= bytes_read);
- CHECK_GE(first_read_buffer_size_, static_cast<size_t>(bytes_read));
- memcpy(buf->data(), first_read_buffer_copy_->data(), bytes_read);
+ // There are two ResourceHandlers in this InterceptingResourceHandler.
+ // |next_handler_| is the old handler and |new_handler_| is the new handler.
+ // As written in the class comment, this class assumes that the old handler
+ // will not set |*defer| in OnResponseCompleted.
+ next_handler_->SetController(controller());
+ next_handler_->OnResponseCompleted(status, defer);
+ DCHECK(!*defer);
- first_read_buffer_copy_ = nullptr;
+ state_ = State::PASS_THROUGH;
+ first_read_buffer_double_ = nullptr;
+ new_handler_->SetController(controller());
+ next_handler_ = std::move(new_handler_);
+ next_handler_->OnResponseCompleted(status, defer);
+}
- // TODO(clamy): Add a unit test to check that the deferral value is properly
- // passed to the caller.
- return next_handler_->OnReadCompleted(bytes_read, defer);
+void InterceptingResourceHandler::Cancel() {
+ DCHECK_NE(State::PASS_THROUGH, state_);
+ controller()->Cancel();
+}
+
+void InterceptingResourceHandler::CancelAndIgnore() {
+ DCHECK_NE(State::PASS_THROUGH, state_);
+ controller()->CancelAndIgnore();
+}
+
+void InterceptingResourceHandler::CancelWithError(int error_code) {
+ DCHECK_NE(State::PASS_THROUGH, state_);
+ controller()->CancelWithError(error_code);
+}
+
+void InterceptingResourceHandler::Resume() {
+ DCHECK_NE(State::PASS_THROUGH, state_);
+ if (state_ == State::STARTING ||
+ state_ == State::WAITING_FOR_ON_READ_COMPLETED) {
+ // Uninteresting Resume: just delegate to the original resource controller.
+ controller()->Resume();
+ return;
+ }
+ bool defer = false;
+ if (!DoLoop(&defer)) {
+ controller()->Cancel();
+ return;
+ }
+
+ if (!defer)
+ controller()->Resume();
}
void InterceptingResourceHandler::UseNewHandler(
std::unique_ptr<ResourceHandler> new_handler,
const std::string& payload_for_old_handler) {
new_handler_ = std::move(new_handler);
- new_handler_->SetController(controller());
+ new_handler_->SetController(this);
payload_for_old_handler_ = payload_for_old_handler;
}
-void InterceptingResourceHandler::SendPayloadToOldHandler() {
- bool defer_ignored = false;
+bool InterceptingResourceHandler::DoLoop(bool* defer) {
+ bool result = true;
+ do {
+ switch (state_) {
+ case State::STARTING:
+ case State::WAITING_FOR_ON_READ_COMPLETED:
+ case State::PASS_THROUGH:
+ NOTREACHED();
+ break;
+ case State::SENDING_ON_WILL_START_TO_NEW_HANDLER:
+ result = SendOnResponseStartedToNewHandler(defer);
+ break;
+ case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER:
+ if (first_read_buffer_double_) {
+ // OnWillRead has been called, so copying the data from
+ // |first_read_buffer_double_| to |first_read_buffer_| will be needed
+ // when OnReadCompleted is called.
+ state_ = State::WAITING_FOR_ON_READ_COMPLETED;
+ } else {
+ // OnWillRead has not been called, so no special handling will be
+ // needed from now on.
+ state_ = State::PASS_THROUGH;
+ next_handler_->SetController(controller());
+ }
+ break;
+ case State::SENDING_PAYLOAD_TO_OLD_HANDLER:
+ result = SendPayloadToOldHandler(defer);
+ break;
+ case State::SENDING_BUFFER_TO_NEW_HANDLER:
+ result = SendFirstReadBufferToNewHandler(defer);
+ break;
+ }
+ } while (result && !*defer &&
+ state_ != State::WAITING_FOR_ON_READ_COMPLETED &&
+ state_ != State::PASS_THROUGH);
+ return result;
+}
+
+bool InterceptingResourceHandler::SendPayloadToOldHandler(bool* defer) {
+ DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_);
+ while (payload_bytes_written_ < payload_for_old_handler_.size()) {
+ scoped_refptr<net::IOBuffer> buffer;
+ int size = 0;
+ if (first_read_buffer_) {
+ // |first_read_buffer_| is a buffer gotten from |next_handler_| via
+ // OnWillRead. Use the buffer.
+ buffer = first_read_buffer_;
+ size = first_read_buffer_size_;
+
+ first_read_buffer_ = nullptr;
+ first_read_buffer_size_ = 0;
+ } else {
+ if (!next_handler_->OnWillRead(&buffer, &size, -1))
+ return false;
+ }
+
+ size = std::min(size, static_cast<int>(payload_for_old_handler_.size() -
+ payload_bytes_written_));
+ memcpy(buffer->data(),
+ payload_for_old_handler_.data() + payload_bytes_written_, size);
+ if (!next_handler_->OnReadCompleted(size, defer))
+ return false;
+ payload_bytes_written_ += size;
+ if (*defer)
+ return true;
+ }
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
if (payload_for_old_handler_.empty()) {
// If there is no payload, just finalize the request on the old handler.
- net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
- net::ERR_ABORTED);
- next_handler_->OnResponseCompleted(status, &defer_ignored);
- DCHECK(!defer_ignored);
- return;
+ status = net::URLRequestStatus::FromError(net::ERR_ABORTED);
}
+ next_handler_->OnResponseCompleted(status, defer);
+ DCHECK(!*defer);
- // Ensure the old ResourceHandler has a buffer that can store the payload.
- scoped_refptr<net::IOBuffer> buf;
- int size = 0;
- if (first_read_buffer_) {
- // The first read buffer can be reused. The data inside it has been copied
- // before calling this function, so it can safely be overriden.
- buf = first_read_buffer_;
- size = first_read_buffer_size_;
- }
+ next_handler_ = std::move(new_handler_);
+ state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER;
+ return next_handler_->OnWillStart(request()->url(), defer);
+}
- // If there is no first read buffer, ask the old ResourceHandler to create a
- // buffer that can contain payload.
- if (!buf)
- next_handler_->OnWillRead(&buf, &size, -1);
-
- DCHECK(buf);
- CHECK_GE(size, static_cast<int>(payload_for_old_handler_.length()));
- memcpy(buf->data(), payload_for_old_handler_.c_str(),
- payload_for_old_handler_.length());
- next_handler_->OnReadCompleted(payload_for_old_handler_.length(),
- &defer_ignored);
- payload_for_old_handler_ = std::string();
- DCHECK(!defer_ignored);
+bool InterceptingResourceHandler::SendOnResponseStartedToNewHandler(
+ bool* defer) {
+ state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER;
+ return next_handler_->OnResponseStarted(response_.get(), defer);
+}
- // Finalize the request.
- net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
- next_handler_->OnResponseCompleted(status, &defer_ignored);
- DCHECK(!defer_ignored);
+bool InterceptingResourceHandler::SendFirstReadBufferToNewHandler(bool* defer) {
+ DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER);
+
+ while (first_read_buffer_bytes_written_ < first_read_buffer_bytes_read_) {
+ scoped_refptr<net::IOBuffer> buf;
+ int size = 0;
+ if (!next_handler_->OnWillRead(&buf, &size, -1))
+ return false;
+ size = std::min(size, static_cast<int>(first_read_buffer_bytes_read_ -
+ first_read_buffer_bytes_written_));
+ memcpy(buf->data(),
+ first_read_buffer_double_->data() + first_read_buffer_bytes_written_,
+ size);
+ if (!next_handler_->OnReadCompleted(size, defer))
+ return false;
+ first_read_buffer_bytes_written_ += size;
+ if (*defer)
+ return true;
+ }
+
+ state_ = State::PASS_THROUGH;
+ first_read_buffer_double_ = nullptr;
+ next_handler_->SetController(controller());
+ return true;
}
} // namespace content
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.h b/chromium/content/browser/loader/intercepting_resource_handler.h
index 8729e5b271e..3c796a406f6 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.h
+++ b/chromium/content/browser/loader/intercepting_resource_handler.h
@@ -14,7 +14,9 @@
#include "content/browser/loader/layered_resource_handler.h"
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
+#include "content/public/browser/resource_controller.h"
#include "net/base/io_buffer.h"
+#include "net/url_request/url_request_status.h"
namespace net {
class URLRequest;
@@ -25,19 +27,34 @@ namespace content {
// ResourceHandler that initiates special handling of the response if needed,
// based on the response's MIME type (starts downloads, sends data to some
// plugin types via a special channel).
+//
+// An InterceptingResourceHandler holds two handlers (|next_handler| and
+// |new_handler|). It assumes the following:
+// - OnResponseStarted on |next_handler| never sets |*defer|.
+// - OnResponseCompleted on |next_handler| never sets |*defer|.
class CONTENT_EXPORT InterceptingResourceHandler
- : public LayeredResourceHandler {
+ : public LayeredResourceHandler,
+ public ResourceController {
public:
InterceptingResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
~InterceptingResourceHandler() override;
// ResourceHandler implementation:
+ void SetController(ResourceController* controller) override;
bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) override;
bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ bool* defer) override;
+
+ // ResourceController implementation:
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
+ void Resume() override;
// Replaces the next handler with |new_handler|, sending
// |payload_for_old_handler| to the old handler. Must be called after
@@ -54,38 +71,70 @@ class CONTENT_EXPORT InterceptingResourceHandler
private:
enum class State {
- // In this state, the InterceptingResourceHandler is waiting for the mime
- // type of the response to be identified, to check if the next handler
- // should be replaced with an appropriate one.
+ // The InterceptingResourceHandler is waiting for the mime type of the
+ // response to be identified, to check if the next handler should be
+ // replaced with an appropriate one.
STARTING,
- // In this state, the InterceptingResourceHandler is waiting to copy the
- // read buffer to the next handler if it was replaced. This is needed
- // because MimeTypeResourceHandler may call OnWillRead before calling
- // OnResponseStarted, that is before the InterceptingResourceHandler
- // replaces the original ResourceHandler of the request. Therefore, the
- // data read at that time should be copied to the new ResourceHandler.
- WAITING_FOR_BUFFER_COPY,
-
- // In this state, the InterceptingResourceHandler has replaced its next
- // ResourceHandler if needed, and has ensured the buffered read data was
- // properly transmitted to the new ResourceHandler. The
- // InterceptingResourceHandler now acts as a pass-through ResourceHandler.
- DONE,
+ // The InterceptingResourceHandler is sending the payload given via
+ // UseNewHandler to the old handler and waiting for its completion via
+ // Resume().
+ SENDING_PAYLOAD_TO_OLD_HANDLER,
+
+ // The InterceptingResourcHandler is calling the new handler's
+ // OnResponseStarted method and waiting for its completion via Resume().
+ // After completion, the InterceptingResourceHandler will transition to
+ // SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER on success.
+ SENDING_ON_WILL_START_TO_NEW_HANDLER,
+
+ // The InterceptingResourcHandler is calling the new handler's
+ // OnResponseStarted method and waiting for its completion via Resume().
+ // After completion, the InterceptingResourceHandler will transition to
+ // WAITING_FOR_ON_READ_COMPLETED on success.
+ SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER,
+
+ // The InterceptingResourcHandler is waiting for OnReadCompleted to be
+ // called.
+ WAITING_FOR_ON_READ_COMPLETED,
+
+ // The InterceptingResourceHandler is sending the old handler's contents to
+ // the new handler and waiting for its completion via Resume().
+ SENDING_BUFFER_TO_NEW_HANDLER,
+
+ // The InterceptingResourceHandler has replaced its next ResourceHandler if
+ // needed, and has ensured the buffered read data was properly transmitted
+ // to the new ResourceHandler. The InterceptingResourceHandler now acts as
+ // a pass-through ResourceHandler.
+ PASS_THROUGH,
};
- void SendPayloadToOldHandler();
+ // Runs necessary operations depending on |state_|. Returns false when an
+ // error happens, and set |*defer| to true if the operation continues upon
+ // return.
+ bool DoLoop(bool* defer);
+
+ // The return value and |defer| has the same meaning as DoLoop.
+ bool SendPayloadToOldHandler(bool* defer);
+ bool SendFirstReadBufferToNewHandler(bool* defer);
+ bool SendOnResponseStartedToNewHandler(bool* defer);
- State state_;
+ State state_ = State::STARTING;
std::unique_ptr<ResourceHandler> new_handler_;
std::string payload_for_old_handler_;
+ size_t payload_bytes_written_ = 0;
// Result of the first read, that may have to be passed to an alternate
// ResourceHandler instead of the original ResourceHandler.
scoped_refptr<net::IOBuffer> first_read_buffer_;
- size_t first_read_buffer_size_;
- scoped_refptr<net::IOBuffer> first_read_buffer_copy_;
+ // Instead of |first_read_buffer_|, this handler creates a new IOBuffer with
+ // the same size and return it to the client.
+ scoped_refptr<net::IOBuffer> first_read_buffer_double_;
+ size_t first_read_buffer_size_ = 0;
+ size_t first_read_buffer_bytes_read_ = 0;
+ size_t first_read_buffer_bytes_written_ = 0;
+
+ scoped_refptr<ResourceResponse> response_;
DISALLOW_COPY_AND_ASSIGN(InterceptingResourceHandler);
};
diff --git a/chromium/content/browser/loader/intercepting_resource_handler_unittest.cc b/chromium/content/browser/loader/intercepting_resource_handler_unittest.cc
index 3ae9dead69e..9f2096ce76c 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler_unittest.cc
@@ -7,13 +7,16 @@
#include <stdint.h>
#include <memory>
+#include <string>
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/loader/test_resource_handler.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_response.h"
@@ -30,102 +33,20 @@ namespace content {
namespace {
-class TestResourceHandler : public ResourceHandler {
+class TestResourceController : public ResourceController {
public:
- // A test version of a ResourceHandler. |request_status| and
- // |final_bytes_read| will be updated when the response is complete with the
- // final status of the request received by the handler, and the total bytes
- // the handler saw.
- explicit TestResourceHandler(net::URLRequestStatus* request_status,
- size_t* final_bytes_read)
- : TestResourceHandler(request_status,
- final_bytes_read,
- true /* on_response_started_result */,
- true /* on_will_read_result */,
- true /* on_read_completed_result */) {}
-
- // This constructor allows to specify return values for OnResponseStarted,
- // OnWillRead and OnReadCompleted.
- TestResourceHandler(net::URLRequestStatus* request_status,
- size_t* final_bytes_read,
- bool on_response_started_result,
- bool on_will_read_result,
- bool on_read_completed_result)
- : ResourceHandler(nullptr),
- buffer_(new net::IOBuffer(2048)),
- request_status_(request_status),
- final_bytes_read_(final_bytes_read),
- on_response_started_result_(on_response_started_result),
- on_will_read_result_(on_will_read_result),
- on_read_completed_result_(on_read_completed_result),
- bytes_read_(0),
- is_completed_(false) {
- memset(buffer_->data(), '\0', 2048);
- }
-
- ~TestResourceHandler() override {}
-
- void SetController(ResourceController* controller) override {}
-
- bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
- ResourceResponse* response,
- bool* defer) override {
- NOTREACHED();
- return false;
- }
-
- bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
- EXPECT_FALSE(is_completed_);
- return on_response_started_result_;
- }
-
- bool OnWillStart(const GURL& url, bool* defer) override {
- EXPECT_FALSE(is_completed_);
- return true;
- }
-
- bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) override {
- EXPECT_FALSE(is_completed_);
- *buf = buffer_;
- *buf_size = 2048;
- memset(buffer_->data(), '\0', 2048);
- return on_will_read_result_;
- }
-
- bool OnReadCompleted(int bytes_read, bool* defer) override {
- EXPECT_FALSE(is_completed_);
- EXPECT_LT(bytes_read, 2048);
- bytes_read_ += bytes_read;
- return on_read_completed_result_;
- }
-
- void OnResponseCompleted(const net::URLRequestStatus& status,
- bool* defer) override {
- EXPECT_FALSE(is_completed_);
- is_completed_ = true;
- *request_status_ = status;
- *final_bytes_read_ = bytes_read_;
- }
-
- void OnDataDownloaded(int bytes_downloaded) override { NOTREACHED(); }
-
- scoped_refptr<net::IOBuffer> buffer() const { return buffer_; }
-
- size_t bytes_read() const { return bytes_read_; }
+ TestResourceController() = default;
+ void Cancel() override {}
+ void CancelAndIgnore() override {}
+ void CancelWithError(int error_code) override {}
+ void Resume() override { ++resume_calls_; }
+
+ int resume_calls() const { return resume_calls_; }
private:
- scoped_refptr<net::IOBuffer> buffer_;
- net::URLRequestStatus* request_status_;
- size_t* final_bytes_read_;
- bool on_response_started_result_;
- bool on_will_read_result_;
- bool on_read_completed_result_;
- size_t bytes_read_;
- bool is_completed_;
-
- DISALLOW_COPY_AND_ASSIGN(TestResourceHandler);
+ int resume_calls_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResourceController);
};
class InterceptingResourceHandlerTest : public testing::Test {
@@ -155,11 +76,10 @@ TEST_F(InterceptingResourceHandlerTest, NoSwitching) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read));
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
TestResourceHandler* old_test_handler = old_handler.get();
- scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -176,7 +96,7 @@ TEST_F(InterceptingResourceHandlerTest, NoSwitching) {
const std::string kData = "The data";
EXPECT_NE(kData, std::string(old_test_handler->buffer()->data()));
- ASSERT_EQ(read_buffer.get(), old_test_handler->buffer());
+ ASSERT_NE(read_buffer.get(), old_test_handler->buffer());
ASSERT_GT(static_cast<size_t>(buf_size), kData.length());
memcpy(read_buffer->data(), kData.c_str(), kData.length());
@@ -203,7 +123,7 @@ TEST_F(InterceptingResourceHandlerTest, NoSwitching) {
EXPECT_TRUE(intercepting_handler->OnReadCompleted(kData2.length(), &defer));
EXPECT_FALSE(defer);
EXPECT_EQ(kData2, std::string(old_test_handler->buffer()->data()));
- EXPECT_EQ(kData.length() + kData2.length(), old_test_handler->bytes_read());
+ EXPECT_EQ(kData + kData2, old_handler_body);
}
// Tests that the data received is transmitted to the newly created
@@ -225,9 +145,9 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchNoPayload) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read));
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -243,17 +163,16 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchNoPayload) {
EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
const std::string kData = "The data";
- ASSERT_EQ(read_buffer.get(), old_buffer.get());
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
ASSERT_GT(static_cast<size_t>(buf_size), kData.length());
memcpy(read_buffer->data(), kData.c_str(), kData.length());
// Simulate the MimeSniffingResourceHandler asking the
// InterceptingResourceHandler to switch to a new handler.
net::URLRequestStatus new_handler_status;
- size_t new_handler_final_bytes_read = 0;
+ std::string new_handler_body;
std::unique_ptr<TestResourceHandler> new_handler_scoped(
- new TestResourceHandler(&new_handler_status,
- &new_handler_final_bytes_read));
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
TestResourceHandler* new_test_handler = new_handler_scoped.get();
intercepting_handler->UseNewHandler(std::move(new_handler_scoped),
std::string());
@@ -265,7 +184,7 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchNoPayload) {
EXPECT_FALSE(old_handler_status.is_success());
EXPECT_EQ(net::ERR_ABORTED, old_handler_status.error());
- EXPECT_EQ(0ul, old_handler_final_bytes_read);
+ EXPECT_EQ(std::string(), old_handler_body);
// It should not have received the download data yet.
EXPECT_NE(kData, std::string(new_test_handler->buffer()->data()));
@@ -289,7 +208,7 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchNoPayload) {
EXPECT_TRUE(intercepting_handler->OnReadCompleted(kData2.length(), &defer));
EXPECT_FALSE(defer);
EXPECT_EQ(kData2, std::string(new_test_handler->buffer()->data()));
- EXPECT_EQ(kData.length() + kData2.length(), new_test_handler->bytes_read());
+ EXPECT_EQ(kData + kData2, new_handler_body);
}
// Tests that the data received is transmitted to the newly created
@@ -311,10 +230,9 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchWithPayload) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
+ std::string old_handler_body;
std::unique_ptr<TestResourceHandler> old_handler_scoped(
- new TestResourceHandler(&old_handler_status,
- &old_handler_final_bytes_read));
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
TestResourceHandler* old_handler = old_handler_scoped.get();
scoped_refptr<net::IOBuffer> old_buffer = old_handler->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
@@ -332,7 +250,7 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchWithPayload) {
EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
const std::string kData = "The data";
- ASSERT_EQ(read_buffer.get(), old_buffer.get());
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
ASSERT_GT(static_cast<size_t>(buf_size), kData.length());
memcpy(read_buffer->data(), kData.c_str(), kData.length());
@@ -340,16 +258,14 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchWithPayload) {
// InterceptingResourceHandler to switch to a new handler.
const std::string kPayload = "The payload";
net::URLRequestStatus new_handler_status;
- size_t new_handler_final_bytes_read = 0;
+ std::string new_handler_body;
std::unique_ptr<TestResourceHandler> new_handler_scoped(
- new TestResourceHandler(&new_handler_status,
- &new_handler_final_bytes_read));
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
TestResourceHandler* new_test_handler = new_handler_scoped.get();
intercepting_handler->UseNewHandler(std::move(new_handler_scoped), kPayload);
// The old handler should not have received the payload yet.
- ASSERT_FALSE(old_handler->bytes_read());
- EXPECT_NE(kPayload, std::string(old_buffer->data()));
+ ASSERT_EQ(std::string(), old_handler_body);
// The response is received. The new ResourceHandler should be used to handle
// the download.
@@ -357,8 +273,7 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchWithPayload) {
EXPECT_FALSE(defer);
// The old handler should have received the payload.
- ASSERT_TRUE(old_handler_final_bytes_read == kPayload.size());
- EXPECT_EQ(kPayload, std::string(old_buffer->data()));
+ EXPECT_EQ(kPayload, old_handler_body);
EXPECT_TRUE(old_handler_status.is_success());
EXPECT_EQ(net::OK, old_handler_status.error());
@@ -385,7 +300,7 @@ TEST_F(InterceptingResourceHandlerTest, HandlerSwitchWithPayload) {
EXPECT_TRUE(intercepting_handler->OnReadCompleted(kData2.length(), &defer));
EXPECT_FALSE(defer);
EXPECT_EQ(kData2, std::string(new_test_handler->buffer()->data()));
- EXPECT_EQ(kData.length() + kData2.length(), new_test_handler->bytes_read());
+ EXPECT_EQ(kData + kData2, new_handler_body);
}
// Tests that the handler behaves properly if the old handler fails will read.
@@ -406,13 +321,10 @@ TEST_F(InterceptingResourceHandlerTest, OldHandlerFailsWillRead) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read,
- true, // on_response_started
- false, // on_will_read
- true)); // on_read_completed
- scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+ old_handler->set_on_will_read_result(false);
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -428,6 +340,61 @@ TEST_F(InterceptingResourceHandlerTest, OldHandlerFailsWillRead) {
EXPECT_FALSE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
}
+// Tests that the handler behaves properly if the new handler fails in
+// OnWillStart.
+TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsOnWillStart) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ RESOURCE_TYPE_MAIN_FRAME,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ net::URLRequestStatus old_handler_status;
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+ scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
+ std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
+ new InterceptingResourceHandler(std::move(old_handler), request.get()));
+
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+
+ // Simulate the MimeSniffingResourceHandler buffering the data.
+ scoped_refptr<net::IOBuffer> read_buffer;
+ int buf_size = 0;
+ bool defer = false;
+ EXPECT_TRUE(intercepting_handler->OnWillStart(GURL(), &defer));
+ EXPECT_FALSE(defer);
+ EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
+
+ const char kData[] = "The data";
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
+ ASSERT_GT(static_cast<size_t>(buf_size), sizeof(kData));
+ memcpy(read_buffer->data(), kData, sizeof(kData));
+
+ // Simulate the MimeSniffingResourceHandler asking the
+ // InterceptingResourceHandler to switch to a new handler.
+ net::URLRequestStatus new_handler_status;
+ std::string new_handler_body;
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->set_on_will_start_result(false);
+ intercepting_handler->UseNewHandler(std::move(new_handler), std::string());
+
+ // The response is received. The new ResourceHandler should tell us to fail.
+ EXPECT_FALSE(intercepting_handler->OnResponseStarted(response.get(), &defer));
+ EXPECT_FALSE(defer);
+}
+
// Tests that the handler behaves properly if the new handler fails response
// started.
TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsResponseStarted) {
@@ -447,9 +414,9 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsResponseStarted) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read));
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -465,19 +432,17 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsResponseStarted) {
EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
const char kData[] = "The data";
- ASSERT_EQ(read_buffer.get(), old_buffer.get());
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
ASSERT_GT(static_cast<size_t>(buf_size), sizeof(kData));
memcpy(read_buffer->data(), kData, sizeof(kData));
// Simulate the MimeSniffingResourceHandler asking the
// InterceptingResourceHandler to switch to a new handler.
net::URLRequestStatus new_handler_status;
- size_t new_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> new_handler(new TestResourceHandler(
- &new_handler_status, &new_handler_final_bytes_read,
- false, // on_response_started
- true, // on_will_read
- true)); // on_read_completed
+ std::string new_handler_body;
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->set_on_response_started_result(false);
intercepting_handler->UseNewHandler(std::move(new_handler), std::string());
// The response is received. The new ResourceHandler should tell us to fail.
@@ -503,9 +468,9 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsWillRead) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read));
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -521,19 +486,17 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsWillRead) {
EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
const char kData[] = "The data";
- ASSERT_EQ(read_buffer.get(), old_buffer.get());
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
ASSERT_GT(static_cast<size_t>(buf_size), sizeof(kData));
memcpy(read_buffer->data(), kData, sizeof(kData));
// Simulate the MimeSniffingResourceHandler asking the
// InterceptingResourceHandler to switch to a new handler.
net::URLRequestStatus new_handler_status;
- size_t new_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> new_handler(new TestResourceHandler(
- &new_handler_status, &new_handler_final_bytes_read,
- true, // on_response_started
- false, // on_will_read
- true)); // on_read_completed
+ std::string new_handler_body;
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->set_on_will_read_result(false);
intercepting_handler->UseNewHandler(std::move(new_handler), std::string());
// The response is received. The new handler should not have been asked to
@@ -568,9 +531,9 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsReadCompleted) {
false); // is_using_lofi
net::URLRequestStatus old_handler_status;
- size_t old_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> old_handler(new TestResourceHandler(
- &old_handler_status, &old_handler_final_bytes_read));
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
new InterceptingResourceHandler(std::move(old_handler), request.get()));
@@ -586,19 +549,17 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsReadCompleted) {
EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
const char kData[] = "The data";
- ASSERT_EQ(read_buffer.get(), old_buffer.get());
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
ASSERT_GT(static_cast<size_t>(buf_size), sizeof(kData));
memcpy(read_buffer->data(), kData, sizeof(kData));
// Simulate the MimeSniffingResourceHandler asking the
// InterceptingResourceHandler to switch to a new handler.
net::URLRequestStatus new_handler_status;
- size_t new_handler_final_bytes_read = 0;
- std::unique_ptr<TestResourceHandler> new_handler(new TestResourceHandler(
- &new_handler_status, &new_handler_final_bytes_read,
- true, // on_response_started
- true, // on_will_read
- false)); // on_read_completed
+ std::string new_handler_body;
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->set_on_read_completed_result(false);
intercepting_handler->UseNewHandler(std::move(new_handler), std::string());
// The response is received.
@@ -613,6 +574,315 @@ TEST_F(InterceptingResourceHandlerTest, NewHandlerFailsReadCompleted) {
EXPECT_FALSE(defer);
}
+// The old handler sets |defer| to true in OnReadCompleted and
+// OnResponseCompleted. The new handler sets |defer| to true in
+// OnResponseStarted and OnReadCompleted.
+TEST_F(InterceptingResourceHandlerTest, DeferredOperations) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ RESOURCE_TYPE_MAIN_FRAME,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ std::unique_ptr<TestResourceController> resource_controller =
+ base::MakeUnique<TestResourceController>();
+ net::URLRequestStatus old_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+ old_handler->SetBufferSize(10);
+ old_handler->set_defer_on_read_completed(true);
+
+ scoped_refptr<net::IOBuffer> old_buffer = old_handler.get()->buffer();
+ std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
+ new InterceptingResourceHandler(std::move(old_handler), request.get()));
+ intercepting_handler->SetController(resource_controller.get());
+
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+
+ // Simulate the MimeSniffingResourceHandler buffering the data.
+ scoped_refptr<net::IOBuffer> read_buffer;
+ int buf_size = 0;
+ bool defer = false;
+ EXPECT_TRUE(intercepting_handler->OnWillStart(GURL(), &defer));
+ EXPECT_FALSE(defer);
+ EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
+
+ const char kData[] = "The data";
+ ASSERT_NE(read_buffer.get(), old_buffer.get());
+ ASSERT_GT(static_cast<size_t>(buf_size), strlen(kData));
+ memcpy(read_buffer->data(), kData, strlen(kData));
+
+ // Simulate the MimeSniffingResourceHandler asking the
+ // InterceptingResourceHandler to switch to a new handler.
+ net::URLRequestStatus new_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+
+ std::string new_handler_body;
+ const std::string kPayload = "The long long long long long payload";
+ ASSERT_GT(kPayload.size(), static_cast<size_t>(buf_size));
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->SetBufferSize(1);
+ new_handler->set_defer_on_will_start(true);
+ new_handler->set_defer_on_response_started(true);
+ new_handler->set_defer_on_read_completed(true);
+ new_handler->set_defer_on_response_completed(true);
+ intercepting_handler->UseNewHandler(std::move(new_handler), kPayload);
+
+ // The response is received, and then deferred by the old handler's
+ // OnReadCompleted method.
+ ASSERT_TRUE(intercepting_handler->OnResponseStarted(response.get(), &defer));
+ ASSERT_TRUE(defer);
+
+ // The old handler has received the first N bytes of the payload synchronously
+ // where N is the size of the buffer exposed via OnWillRead.
+ EXPECT_EQ("The long l", old_handler_body);
+ EXPECT_EQ(std::string(), new_handler_body);
+ EXPECT_EQ(old_handler_status.status(), net::URLRequestStatus::IO_PENDING);
+ EXPECT_EQ(new_handler_status.status(), net::URLRequestStatus::IO_PENDING);
+
+ // Run until the new handler's OnWillStart method defers the request.
+ intercepting_handler->Resume();
+ EXPECT_EQ(0, resource_controller->resume_calls());
+ EXPECT_EQ(kPayload, old_handler_body);
+ EXPECT_EQ(std::string(), new_handler_body);
+ EXPECT_EQ(old_handler_status.status(), net::URLRequestStatus::SUCCESS);
+ EXPECT_EQ(new_handler_status.status(), net::URLRequestStatus::IO_PENDING);
+
+ // Run until the new handler's OnResponseStarted method defers the request.
+ intercepting_handler->Resume();
+ EXPECT_EQ(0, resource_controller->resume_calls());
+ EXPECT_EQ(std::string(), new_handler_body);
+ EXPECT_EQ(old_handler_status.status(), net::URLRequestStatus::SUCCESS);
+ EXPECT_EQ(new_handler_status.status(), net::URLRequestStatus::IO_PENDING);
+
+ // Resuming should finally call back into the ResourceController.
+ intercepting_handler->Resume();
+ EXPECT_EQ(1, resource_controller->resume_calls());
+
+ // Data is read, the new handler defers completion of the read.
+ defer = false;
+ ASSERT_TRUE(intercepting_handler->OnReadCompleted(strlen(kData), &defer));
+ ASSERT_TRUE(defer);
+
+ EXPECT_EQ(kPayload, old_handler_body);
+ EXPECT_EQ("T", new_handler_body);
+
+ intercepting_handler->Resume();
+ EXPECT_EQ(2, resource_controller->resume_calls());
+ EXPECT_EQ(kPayload, old_handler_body);
+ EXPECT_EQ(kData, new_handler_body);
+
+ EXPECT_EQ(old_handler_status.status(), net::URLRequestStatus::SUCCESS);
+ EXPECT_EQ(new_handler_status.status(), net::URLRequestStatus::IO_PENDING);
+
+ defer = false;
+ intercepting_handler->OnResponseCompleted({net::URLRequestStatus::SUCCESS, 0},
+ &defer);
+ ASSERT_TRUE(defer);
+ EXPECT_EQ(old_handler_status.status(), net::URLRequestStatus::SUCCESS);
+ EXPECT_EQ(new_handler_status.status(), net::URLRequestStatus::SUCCESS);
+}
+
+// Test cancellation where there is only the old handler in an
+// InterceptingResourceHandler.
+TEST_F(InterceptingResourceHandlerTest, CancelOldHandler) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ RESOURCE_TYPE_MAIN_FRAME,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ std::unique_ptr<TestResourceController> resource_controller =
+ base::MakeUnique<TestResourceController>();
+ net::URLRequestStatus old_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+
+ std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
+ new InterceptingResourceHandler(std::move(old_handler), request.get()));
+ intercepting_handler->SetController(resource_controller.get());
+
+ EXPECT_EQ(net::URLRequestStatus::IO_PENDING, old_handler_status.status());
+
+ bool defer = false;
+ intercepting_handler->OnResponseCompleted(
+ {net::URLRequestStatus::CANCELED, net::ERR_FAILED}, &defer);
+ ASSERT_FALSE(defer);
+ EXPECT_EQ(0, resource_controller->resume_calls());
+ EXPECT_EQ(net::URLRequestStatus::CANCELED, old_handler_status.status());
+}
+
+// Test cancellation where there is only the new handler in an
+// InterceptingResourceHandler.
+TEST_F(InterceptingResourceHandlerTest, CancelNewHandler) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ RESOURCE_TYPE_MAIN_FRAME,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ std::unique_ptr<TestResourceController> resource_controller =
+ base::MakeUnique<TestResourceController>();
+ net::URLRequestStatus old_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+
+ std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
+ new InterceptingResourceHandler(std::move(old_handler), request.get()));
+ intercepting_handler->SetController(resource_controller.get());
+
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+
+ // Simulate the MimeSniffingResourceHandler buffering the data.
+ scoped_refptr<net::IOBuffer> read_buffer;
+ int buf_size = 0;
+ bool defer = false;
+ EXPECT_TRUE(intercepting_handler->OnWillStart(GURL(), &defer));
+ EXPECT_FALSE(defer);
+ EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
+
+ const char kData[] = "The data";
+ ASSERT_GT(static_cast<size_t>(buf_size), strlen(kData));
+ memcpy(read_buffer->data(), kData, strlen(kData));
+
+ // Simulate the MimeSniffingResourceHandler asking the
+ // InterceptingResourceHandler to switch to a new handler.
+ net::URLRequestStatus new_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+
+ std::string new_handler_body;
+ const std::string kPayload = "The payload";
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->SetBufferSize(1);
+ new_handler->set_defer_on_response_started(true);
+ new_handler->set_defer_on_response_completed(true);
+ intercepting_handler->UseNewHandler(std::move(new_handler), kPayload);
+
+ // The response is received.
+ ASSERT_TRUE(intercepting_handler->OnResponseStarted(response.get(), &defer));
+ ASSERT_TRUE(defer);
+
+ EXPECT_EQ(net::URLRequestStatus::SUCCESS, old_handler_status.status());
+ EXPECT_EQ(net::URLRequestStatus::IO_PENDING, new_handler_status.status());
+
+ defer = false;
+ intercepting_handler->OnResponseCompleted(
+ {net::URLRequestStatus::CANCELED, net::ERR_FAILED}, &defer);
+ ASSERT_TRUE(defer);
+ EXPECT_EQ(0, resource_controller->resume_calls());
+ EXPECT_EQ(net::URLRequestStatus::SUCCESS, old_handler_status.status());
+ EXPECT_EQ(net::URLRequestStatus::CANCELED, new_handler_status.status());
+}
+
+// Test cancellation where there are both the old and the new handlers in an
+// InterceptingResourceHandler.
+TEST_F(InterceptingResourceHandlerTest, CancelBothHandlers) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ RESOURCE_TYPE_MAIN_FRAME,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ std::unique_ptr<TestResourceController> resource_controller =
+ base::MakeUnique<TestResourceController>();
+ net::URLRequestStatus old_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+ std::string old_handler_body;
+ std::unique_ptr<TestResourceHandler> old_handler(
+ new TestResourceHandler(&old_handler_status, &old_handler_body));
+ old_handler->set_defer_on_read_completed(true);
+
+ std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
+ new InterceptingResourceHandler(std::move(old_handler), request.get()));
+ intercepting_handler->SetController(resource_controller.get());
+
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+
+ // Simulate the MimeSniffingResourceHandler buffering the data.
+ scoped_refptr<net::IOBuffer> read_buffer;
+ int buf_size = 0;
+ bool defer = false;
+ EXPECT_TRUE(intercepting_handler->OnWillStart(GURL(), &defer));
+ EXPECT_FALSE(defer);
+ EXPECT_TRUE(intercepting_handler->OnWillRead(&read_buffer, &buf_size, -1));
+
+ const char kData[] = "The data";
+ ASSERT_GT(static_cast<size_t>(buf_size), strlen(kData));
+ memcpy(read_buffer->data(), kData, strlen(kData));
+
+ // Simulate the MimeSniffingResourceHandler asking the
+ // InterceptingResourceHandler to switch to a new handler.
+ net::URLRequestStatus new_handler_status = {net::URLRequestStatus::IO_PENDING,
+ 0};
+
+ std::string new_handler_body;
+ const std::string kPayload = "The payload";
+ std::unique_ptr<TestResourceHandler> new_handler(
+ new TestResourceHandler(&new_handler_status, &new_handler_body));
+ new_handler->SetBufferSize(1);
+ new_handler->set_defer_on_response_completed(true);
+ intercepting_handler->UseNewHandler(std::move(new_handler), kPayload);
+
+ // The response is received.
+ ASSERT_TRUE(intercepting_handler->OnResponseStarted(response.get(), &defer));
+ ASSERT_TRUE(defer);
+
+ EXPECT_EQ(net::URLRequestStatus::IO_PENDING, old_handler_status.status());
+ EXPECT_EQ(net::URLRequestStatus::IO_PENDING, new_handler_status.status());
+
+ defer = false;
+ intercepting_handler->OnResponseCompleted(
+ {net::URLRequestStatus::CANCELED, net::ERR_FAILED}, &defer);
+ ASSERT_TRUE(defer);
+ EXPECT_EQ(0, resource_controller->resume_calls());
+ EXPECT_EQ(net::URLRequestStatus::CANCELED, old_handler_status.status());
+ EXPECT_EQ(net::URLRequestStatus::CANCELED, new_handler_status.status());
+}
+
} // namespace
} // 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 bba9d01aa6a..3e5e414ff1c 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -406,7 +406,7 @@ bool MimeSniffingResourceHandler::MaybeStartInterception(bool* defer) {
return true;
}
- // This is request is a download,
+ // This request is a download.
if (!CheckResponseIsNotProvisional())
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 4e8e912e4b1..92a8a1fca76 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
@@ -12,10 +12,12 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/loader/intercepting_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/test_resource_handler.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
@@ -33,97 +35,6 @@ namespace content {
namespace {
-class TestResourceHandler : public ResourceHandler {
- public:
- TestResourceHandler(bool response_started_succeeds,
- bool defer_on_response_started,
- bool will_read_succeeds,
- bool read_completed_succeeds,
- bool defer_on_read_completed)
- : ResourceHandler(nullptr),
- buffer_(new net::IOBuffer(2048)),
- response_started_succeeds_(response_started_succeeds),
- defer_on_response_started_(defer_on_response_started),
- will_read_succeeds_(will_read_succeeds),
- read_completed_succeeds_(read_completed_succeeds),
- defer_on_read_completed_(defer_on_read_completed),
- on_will_start_called_(0),
- on_request_redirected_called_(0),
- on_response_started_called_(0),
- on_will_read_called_(0),
- on_read_completed_called_(0) {}
-
- void SetController(ResourceController* controller) override {}
-
- bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
- ResourceResponse* response,
- bool* defer) override {
- on_request_redirected_called_++;
- NOTREACHED();
- return false;
- }
-
- bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
- on_response_started_called_++;
- if (defer_on_response_started_)
- *defer = true;
- return response_started_succeeds_;
- }
-
- bool OnWillStart(const GURL& url, bool* defer) override {
- on_will_start_called_++;
- return false;
- }
-
- bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) override {
- on_will_read_called_++;
- *buf = buffer_;
- *buf_size = 2048;
- return will_read_succeeds_;
- }
-
- bool OnReadCompleted(int bytes_read, bool* defer) override {
- DCHECK_LT(bytes_read, 2048);
- on_read_completed_called_++;
- if (defer_on_read_completed_)
- *defer = true;
- return read_completed_succeeds_;
- }
-
- void OnResponseCompleted(const net::URLRequestStatus& status,
- bool* defer) override {}
-
- void OnDataDownloaded(int bytes_downloaded) override { NOTREACHED(); }
-
- scoped_refptr<net::IOBuffer> buffer() { return buffer_; }
-
- int on_will_start_called() const { return on_will_start_called_; }
- int on_request_redirected_called() const {
- return on_request_redirected_called_;
- }
- int on_response_started_called() const { return on_response_started_called_; }
- int on_will_read_called() const { return on_will_read_called_; }
- int on_read_completed_called() const { return on_read_completed_called_; }
-
- private:
- scoped_refptr<net::IOBuffer> buffer_;
- bool response_started_succeeds_;
- bool defer_on_response_started_;
- bool will_read_succeeds_;
- bool read_completed_succeeds_;
- bool defer_on_read_completed_;
-
- int on_will_start_called_;
- int on_request_redirected_called_;
- int on_response_started_called_;
- int on_will_read_called_;
- int on_read_completed_called_;
-
- DISALLOW_COPY_AND_ASSIGN(TestResourceHandler);
-};
-
class TestResourceDispatcherHostDelegate
: public ResourceDispatcherHostDelegate {
public:
@@ -179,7 +90,8 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
private:
std::unique_ptr<ResourceHandler> CreateNewResourceHandler() {
std::unique_ptr<TestResourceHandler> new_resource_handler(
- new TestResourceHandler(false, false, true, true, false));
+ new TestResourceHandler());
+ new_resource_handler->set_on_response_started_result(false);
new_resource_handler_ = new_resource_handler.get();
return std::move(new_resource_handler);
}
@@ -340,12 +252,14 @@ MimeSniffingResourceHandlerTest::TestAcceptHeaderSettingWithURLRequest(
true, // is_async
false); // is_using_lofi
+ std::unique_ptr<TestResourceHandler> scoped_test_handler(
+ new TestResourceHandler());
+ scoped_test_handler->set_on_response_started_result(false);
+
std::unique_ptr<ResourceHandler> mime_sniffing_handler(
- new MimeSniffingResourceHandler(
- std::unique_ptr<ResourceHandler>(
- new TestResourceHandler(false, false, false, false, false)),
- nullptr, nullptr, nullptr, request,
- REQUEST_CONTEXT_TYPE_UNSPECIFIED));
+ new MimeSniffingResourceHandler(std::move(scoped_test_handler), nullptr,
+ nullptr, nullptr, request,
+ REQUEST_CONTEXT_TYPE_UNSPECIFIED));
bool defer = false;
mime_sniffing_handler->OnWillStart(request->url(), &defer);
@@ -380,13 +294,16 @@ bool MimeSniffingResourceHandlerTest::TestStreamIsIntercepted(
host.SetDelegate(&host_delegate);
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
+
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
- new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
+ new InterceptingResourceHandler(base::MakeUnique<TestResourceHandler>(),
nullptr));
+ std::unique_ptr<TestResourceHandler> scoped_test_handler(
+ new TestResourceHandler());
+ scoped_test_handler->set_on_response_started_result(false);
std::unique_ptr<ResourceHandler> mime_handler(new MimeSniffingResourceHandler(
- std::unique_ptr<ResourceHandler>(
- new TestResourceHandler(false, false, false, false, false)),
- &host, &plugin_service, intercepting_handler.get(), request.get(),
+ std::unique_ptr<ResourceHandler>(std::move(scoped_test_handler)), &host,
+ &plugin_service, intercepting_handler.get(), request.get(),
REQUEST_CONTEXT_TYPE_UNSPECIFIED));
TestResourceController resource_controller;
@@ -397,6 +314,9 @@ bool MimeSniffingResourceHandlerTest::TestStreamIsIntercepted(
response->head.mime_type = "application/pdf";
bool defer = false;
+ mime_handler->OnWillStart(request->url(), &defer);
+ EXPECT_FALSE(defer);
+
mime_handler->OnResponseStarted(response.get(), &defer);
content::RunAllPendingInMessageLoop();
@@ -433,12 +353,16 @@ void MimeSniffingResourceHandlerTest::TestHandlerSniffing(
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
- new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
+ new InterceptingResourceHandler(base::MakeUnique<TestResourceHandler>(),
nullptr));
- std::unique_ptr<TestResourceHandler> scoped_test_handler =
- std::unique_ptr<TestResourceHandler>(new TestResourceHandler(
- response_started, defer_response_started, will_read, read_completed,
- defer_read_completed));
+
+ std::unique_ptr<TestResourceHandler> scoped_test_handler(
+ new TestResourceHandler());
+ scoped_test_handler->set_on_response_started_result(response_started);
+ scoped_test_handler->set_defer_on_response_started(defer_response_started);
+ scoped_test_handler->set_on_will_read_result(will_read);
+ scoped_test_handler->set_on_read_completed_result(read_completed);
+ scoped_test_handler->set_defer_on_read_completed(defer_read_completed);
TestResourceHandler* test_handler = scoped_test_handler.get();
std::unique_ptr<MimeSniffingResourceHandler> mime_sniffing_handler(
new MimeSniffingResourceHandler(std::move(scoped_test_handler), &host,
@@ -594,13 +518,16 @@ void MimeSniffingResourceHandlerTest::TestHandlerNoSniffing(
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
- new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
+ new InterceptingResourceHandler(base::MakeUnique<TestResourceHandler>(),
nullptr));
- std::unique_ptr<TestResourceHandler> scoped_test_handler =
- std::unique_ptr<TestResourceHandler>(new TestResourceHandler(
- response_started, defer_response_started, will_read, read_completed,
- defer_read_completed));
+ std::unique_ptr<TestResourceHandler> scoped_test_handler(
+ new TestResourceHandler());
+ scoped_test_handler->set_on_response_started_result(response_started);
+ scoped_test_handler->set_defer_on_response_started(defer_response_started);
+ scoped_test_handler->set_on_will_read_result(will_read);
+ scoped_test_handler->set_on_read_completed_result(read_completed);
+ scoped_test_handler->set_defer_on_read_completed(defer_read_completed);
TestResourceHandler* test_handler = scoped_test_handler.get();
std::unique_ptr<MimeSniffingResourceHandler> mime_sniffing_handler(
new MimeSniffingResourceHandler(std::move(scoped_test_handler), &host,
@@ -988,18 +915,22 @@ TEST_F(MimeSniffingResourceHandlerTest, 304Handling) {
TestFakePluginService plugin_service(false, false);
std::unique_ptr<ResourceHandler> intercepting_handler(
- new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
+ new InterceptingResourceHandler(base::MakeUnique<TestResourceHandler>(),
nullptr));
std::unique_ptr<ResourceHandler> mime_handler(new MimeSniffingResourceHandler(
- std::unique_ptr<ResourceHandler>(
- new TestResourceHandler(true, false, true, true, false)),
- &host, &plugin_service,
+ std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host,
+ &plugin_service,
static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
request.get(), REQUEST_CONTEXT_TYPE_UNSPECIFIED));
TestResourceController resource_controller;
mime_handler->SetController(&resource_controller);
+ // Request starts.
+ bool defer = false;
+ mime_handler->OnWillStart(request->url(), &defer);
+ EXPECT_FALSE(defer);
+
// Simulate a 304 response.
scoped_refptr<ResourceResponse> response(new ResourceResponse);
// The MIME type isn't important but it shouldn't be empty.
@@ -1008,7 +939,6 @@ TEST_F(MimeSniffingResourceHandlerTest, 304Handling) {
// The response is received. No new ResourceHandler should be created to
// handle the download.
- bool defer = false;
mime_handler->OnResponseStarted(response.get(), &defer);
EXPECT_FALSE(defer);
EXPECT_FALSE(host.new_resource_handler());
@@ -1036,14 +966,12 @@ TEST_F(MimeSniffingResourceHandlerTest, FetchShouldDisableMimeSniffing) {
TestFakePluginService plugin_service(false, false);
std::unique_ptr<InterceptingResourceHandler> intercepting_handler(
- new InterceptingResourceHandler(nullptr, nullptr));
+ new InterceptingResourceHandler(base::MakeUnique<TestResourceHandler>(),
+ nullptr));
std::unique_ptr<TestResourceHandler> scoped_test_handler(
- new TestResourceHandler(false, // response_started
- false, // defer_response_started
- true, // will_read,
- true, // read_completed,
- false)); // defer_read_completed
+ new TestResourceHandler());
+ scoped_test_handler->set_on_response_started_result(false);
std::unique_ptr<ResourceHandler> mime_sniffing_handler(
new MimeSniffingResourceHandler(std::move(scoped_test_handler), &host,
&plugin_service,
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index b66c389d3ff..1288fe45136 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -16,9 +16,12 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/common/resource_request_completion_status.h"
+#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/common/resource_response.h"
#include "mojo/public/c/system/data_pipe.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
@@ -103,14 +106,18 @@ class MojoAsyncResourceHandler::WriterIOBuffer final
MojoAsyncResourceHandler::MojoAsyncResourceHandler(
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client)
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client)
: ResourceHandler(request),
rdh_(rdh),
binding_(this, std::move(mojo_request)),
url_loader_client_(std::move(url_loader_client)) {
DCHECK(url_loader_client_);
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)));
}
MojoAsyncResourceHandler::~MojoAsyncResourceHandler() {
@@ -122,8 +129,24 @@ bool MojoAsyncResourceHandler::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
- // Not implemented.
- return false;
+ // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by
+ // OnWillRead.
+ DCHECK(!shared_writer_);
+
+ *defer = true;
+ request()->LogBlockedBy("MojoAsyncResourceHandler");
+ 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();
+ // TODO(davidben): Is it necessary to pass the new first party URL for
+ // cookies? The only case where it can change is top-level navigation requests
+ // and hopefully those will eventually all be owned by the browser. It's
+ // possible this is still needed while renderer-owned ones exist.
+ url_loader_client_->OnReceiveRedirect(redirect_info, response->head);
+ return true;
}
bool MojoAsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
@@ -213,8 +236,10 @@ bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
buffer_bytes_read_ = bytes_read;
if (!CopyReadDataToDataPipe(defer))
return false;
- if (*defer)
- OnDefer();
+ if (*defer) {
+ request()->LogBlockedBy("MojoAsyncResourceHandler");
+ did_defer_on_writing_ = true;
+ }
return true;
}
@@ -224,25 +249,42 @@ bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
// doesn't have |defer| parameter.
if (!AllocateWriterIOBuffer(&buffer_, defer))
return false;
- if (*defer)
- OnDefer();
+ if (*defer) {
+ request()->LogBlockedBy("MojoAsyncResourceHandler");
+ did_defer_on_writing_ = true;
+ }
return true;
}
void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- // Not implemented.
+ int64_t total_received_bytes = request()->GetTotalReceivedBytes();
+ int64_t bytes_to_report =
+ total_received_bytes - reported_total_received_bytes_;
+ reported_total_received_bytes_ = total_received_bytes;
+ DCHECK_LE(0, bytes_to_report);
+
+ url_loader_client_->OnDataDownloaded(bytes_downloaded, bytes_to_report);
}
void MojoAsyncResourceHandler::FollowRedirect() {
- NOTIMPLEMENTED();
-}
+ if (!request()->status().is_success()) {
+ DVLOG(1) << "FollowRedirect for invalid request";
+ return;
+ }
+ if (!did_defer_on_redirect_) {
+ DVLOG(1) << "Malformed FollowRedirect request";
+ ReportBadMessage("Malformed FollowRedirect request");
+ return;
+ }
-void MojoAsyncResourceHandler::Cancel() {
- NOTIMPLEMENTED();
+ DCHECK(!did_defer_on_writing_);
+ did_defer_on_redirect_ = false;
+ request()->LogUnblocked();
+ controller()->Resume();
}
-void MojoAsyncResourceHandler::ResumeForTesting() {
- Resume();
+void MojoAsyncResourceHandler::OnWritableForTesting() {
+ OnWritable(MOJO_RESULT_OK);
}
void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) {
@@ -344,54 +386,56 @@ bool MojoAsyncResourceHandler::AllocateWriterIOBuffer(
return true;
}
-void MojoAsyncResourceHandler::Resume() {
- if (!did_defer_)
+bool MojoAsyncResourceHandler::CheckForSufficientResource() {
+ if (has_checked_for_sufficient_resources_)
+ return true;
+ has_checked_for_sufficient_resources_ = true;
+
+ if (rdh_->HasSufficientResourcesForRequest(request()))
+ return true;
+
+ controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
+ return false;
+}
+
+void MojoAsyncResourceHandler::OnWritable(MojoResult result) {
+ if (!did_defer_on_writing_)
return;
- bool defer = false;
+ DCHECK(!did_defer_on_redirect_);
+ did_defer_on_writing_ = false;
+
if (is_using_io_buffer_not_from_writer_) {
// |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents
// to the data pipe.
DCHECK_GT(buffer_bytes_read_, 0u);
- if (!CopyReadDataToDataPipe(&defer)) {
+ if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) {
controller()->CancelWithError(net::ERR_FAILED);
return;
}
} else {
// Allocate a buffer for the next OnWillRead call here.
- if (!AllocateWriterIOBuffer(&buffer_, &defer)) {
+ if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) {
controller()->CancelWithError(net::ERR_FAILED);
return;
}
}
- if (defer) {
+ if (did_defer_on_writing_) {
// Continue waiting.
return;
}
- did_defer_ = false;
request()->LogUnblocked();
controller()->Resume();
}
-void MojoAsyncResourceHandler::OnDefer() {
- request()->LogBlockedBy("MojoAsyncResourceHandler");
- did_defer_ = true;
-}
-
-bool MojoAsyncResourceHandler::CheckForSufficientResource() {
- if (has_checked_for_sufficient_resources_)
- return true;
- has_checked_for_sufficient_resources_ = true;
-
- if (rdh_->HasSufficientResourcesForRequest(request()))
- return true;
-
- controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
- return false;
+void MojoAsyncResourceHandler::Cancel() {
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer(
+ GlobalRequestID(info->GetChildID(), info->GetRequestID()));
}
-void MojoAsyncResourceHandler::OnWritable(MojoResult unused) {
- Resume();
+void MojoAsyncResourceHandler::ReportBadMessage(const std::string& error) {
+ mojo::ReportBadMessage(error);
}
} // namespace content
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index 5df87fd090e..ae47419a956 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -16,7 +16,7 @@
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
#include "content/common/url_loader.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/system/watcher.h"
#include "net/base/io_buffer.h"
#include "url/gurl.h"
@@ -27,17 +27,13 @@ class URLRequest;
namespace content {
class ResourceDispatcherHostImpl;
-class ResourceRequestInfoImpl;
struct ResourceResponse;
// Used to complete an asynchronous resource request in response to resource
// load events from the resource dispatcher host. This class is used only
// when LoadingWithMojo runtime flag is enabled.
//
-// TODO(yhirano): Implement redirects.
-// TODO(yhirano): Implement downloading to file.
// TODO(yhirano): Add histograms.
-// TODO(yhirano): Set zoom level.
// TODO(yhirano): Send cached metadata.
//
// This class can be inherited only for tests.
@@ -48,8 +44,8 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
MojoAsyncResourceHandler(
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client);
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client);
~MojoAsyncResourceHandler() override;
// ResourceHandler implementation:
@@ -68,9 +64,8 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
// mojom::URLLoader implementation
void FollowRedirect() override;
- void Cancel() override;
- void ResumeForTesting();
+ void OnWritableForTesting();
static void SetAllocationSizeForTesting(size_t size);
static constexpr size_t kDefaultAllocationSize = 512 * 1024;
@@ -92,23 +87,26 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
bool AllocateWriterIOBuffer(scoped_refptr<net::IOBufferWithSize>* buf,
bool* defer);
- void Resume();
- void OnDefer();
bool CheckForSufficientResource();
void OnWritable(MojoResult result);
+ void Cancel();
+ // This function can be overriden only for tests.
+ virtual void ReportBadMessage(const std::string& error);
ResourceDispatcherHostImpl* rdh_;
- mojo::Binding<mojom::URLLoader> binding_;
+ mojo::AssociatedBinding<mojom::URLLoader> binding_;
bool has_checked_for_sufficient_resources_ = false;
bool sent_received_response_message_ = false;
bool is_using_io_buffer_not_from_writer_ = false;
- bool did_defer_ = false;
+ bool did_defer_on_writing_ = false;
+ bool did_defer_on_redirect_ = false;
base::TimeTicks response_started_ticks_;
+ int64_t reported_total_received_bytes_ = 0;
mojo::Watcher handle_watcher_;
std::unique_ptr<mojom::URLLoader> url_loader_;
- mojom::URLLoaderClientPtr url_loader_client_;
+ mojom::URLLoaderClientAssociatedPtr url_loader_client_;
scoped_refptr<net::IOBufferWithSize> buffer_;
size_t buffer_offset_ = 0;
size_t buffer_bytes_read_ = 0;
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 5386d6e906f..4ad1ba638fe 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -33,6 +33,7 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/types.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/auth.h"
#include "net/base/net_errors.h"
@@ -98,12 +99,7 @@ class TestResourceDispatcherHostDelegate final
bool HandleExternalProtocol(
const GURL& url,
- int child_id,
- const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
- bool is_main_frame,
- ui::PageTransition page_transition,
- bool has_user_gesture,
- ResourceContext* resource_context) override {
+ ResourceRequestInfo* resource_request_info) override {
ADD_FAILURE() << "HandleExternalProtocol should not be called.";
return false;
}
@@ -189,6 +185,10 @@ class TestResourceController : public ResourceController {
}
void CancelWithError(int error_code) override {
+ // While cancelling more than once is legal, none of these tests should do
+ // it.
+ EXPECT_FALSE(is_cancel_with_error_called_);
+
is_cancel_with_error_called_ = true;
error_ = error_code;
if (quit_closure_)
@@ -228,8 +228,8 @@ class MojoAsyncResourceHandlerWithCustomDataPipeOperations
MojoAsyncResourceHandlerWithCustomDataPipeOperations(
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client)
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client)
: MojoAsyncResourceHandler(request,
rdh,
std::move(mojo_request),
@@ -246,6 +246,7 @@ class MojoAsyncResourceHandlerWithCustomDataPipeOperations
is_end_write_expectation_set_ = true;
end_write_expectation_ = end_write_expectation;
}
+ bool has_received_bad_message() const { return has_received_bad_message_; }
private:
MojoResult BeginWrite(void** data, uint32_t* available) override {
@@ -258,9 +259,13 @@ class MojoAsyncResourceHandlerWithCustomDataPipeOperations
return end_write_expectation_;
return MojoAsyncResourceHandler::EndWrite(written);
}
+ void ReportBadMessage(const std::string& error) override {
+ has_received_bad_message_ = true;
+ }
bool is_begin_write_expectation_set_ = false;
bool is_end_write_expectation_set_ = false;
+ bool has_received_bad_message_ = false;
MojoResult begin_write_expectation_ = MOJO_RESULT_UNKNOWN;
MojoResult end_write_expectation_ = MOJO_RESULT_UNKNOWN;
@@ -268,6 +273,43 @@ class MojoAsyncResourceHandlerWithCustomDataPipeOperations
MojoAsyncResourceHandlerWithCustomDataPipeOperations);
};
+class TestURLLoaderFactory final : public mojom::URLLoaderFactory {
+ public:
+ TestURLLoaderFactory() {}
+ ~TestURLLoaderFactory() override {}
+
+ void CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) override {
+ loader_request_ = std::move(request);
+ client_ptr_info_ = std::move(client_ptr_info);
+ }
+
+ mojom::URLLoaderAssociatedRequest PassLoaderRequest() {
+ return std::move(loader_request_);
+ }
+
+ mojom::URLLoaderClientAssociatedPtrInfo PassClientPtrInfo() {
+ return std::move(client_ptr_info_);
+ }
+
+ void SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ const SyncLoadCallback& callback) override {
+ NOTREACHED();
+ }
+
+ private:
+ mojom::URLLoaderAssociatedRequest loader_request_;
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestURLLoaderFactory);
+};
+
class MojoAsyncResourceHandlerTestBase {
public:
MojoAsyncResourceHandlerTestBase()
@@ -295,9 +337,28 @@ class MojoAsyncResourceHandlerTestBase {
true, // is_async
false // is_using_lofi
);
+
+ ResourceRequest request;
+ base::WeakPtr<mojo::StrongBinding<mojom::URLLoaderFactory>> weak_binding =
+ mojo::MakeStrongBinding(base::MakeUnique<TestURLLoaderFactory>(),
+ mojo::GetProxy(&url_loader_factory_));
+
+ url_loader_factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&url_loader_proxy_,
+ url_loader_factory_.associated_group()),
+ 0, 0, request, url_loader_client_.CreateRemoteAssociatedPtrInfo(
+ url_loader_factory_.associated_group()));
+
+ url_loader_factory_.FlushForTesting();
+ DCHECK(weak_binding);
+ TestURLLoaderFactory* factory_impl =
+ static_cast<TestURLLoaderFactory*>(weak_binding->impl());
+
+ mojom::URLLoaderClientAssociatedPtr client_ptr;
+ client_ptr.Bind(factory_impl->PassClientPtrInfo());
handler_.reset(new MojoAsyncResourceHandlerWithCustomDataPipeOperations(
- request_.get(), &rdh_, nullptr,
- url_loader_client_.CreateInterfacePtrAndBind()));
+ request_.get(), &rdh_, factory_impl->PassLoaderRequest(),
+ std::move(client_ptr)));
handler_->SetController(&resource_controller_);
}
@@ -349,6 +410,8 @@ class MojoAsyncResourceHandlerTestBase {
TestBrowserThreadBundle thread_bundle_;
TestResourceDispatcherHostDelegate rdh_delegate_;
ResourceDispatcherHostImpl rdh_;
+ mojom::URLLoaderFactoryPtr url_loader_factory_;
+ mojom::URLLoaderAssociatedPtr url_loader_proxy_;
TestURLLoaderClient url_loader_client_;
TestResourceController resource_controller_;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -781,7 +844,7 @@ TEST_F(MojoAsyncResourceHandlerTest,
url_loader_client_.RunUntilResponseBodyArrived();
ASSERT_TRUE(url_loader_client_.response_body().is_valid());
handler_->ResetBeginWriteExpectation();
- handler_->ResumeForTesting();
+ handler_->OnWritableForTesting();
std::string actual;
while (actual.size() < written) {
@@ -1020,6 +1083,76 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, CancelWhileWaiting) {
EXPECT_EQ(0, resource_controller_.num_resume_calls());
}
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
+ rdh_delegate_.set_num_on_response_started_calls_expectation(1);
+ bool defer = false;
+
+ ASSERT_TRUE(handler_->OnWillStart(request_->url(), &defer));
+ ASSERT_FALSE(defer);
+ scoped_refptr<ResourceResponse> response = new ResourceResponse();
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 301;
+ ASSERT_TRUE(
+ handler_->OnRequestRedirected(redirect_info, response.get(), &defer));
+ ASSERT_TRUE(defer);
+
+ ASSERT_FALSE(url_loader_client_.has_received_response());
+ ASSERT_FALSE(url_loader_client_.has_received_redirect());
+ url_loader_client_.RunUntilRedirectReceived();
+
+ ASSERT_FALSE(url_loader_client_.has_received_response());
+ ASSERT_TRUE(url_loader_client_.has_received_redirect());
+ EXPECT_EQ(301, url_loader_client_.redirect_info().status_code);
+
+ EXPECT_EQ(0, resource_controller_.num_resume_calls());
+ handler_->FollowRedirect();
+ EXPECT_EQ(1, resource_controller_.num_resume_calls());
+
+ url_loader_client_.ClearHasReceivedRedirect();
+ // Redirect once more.
+ defer = false;
+ redirect_info.status_code = 302;
+ ASSERT_TRUE(
+ handler_->OnRequestRedirected(redirect_info, response.get(), &defer));
+ ASSERT_TRUE(defer);
+
+ ASSERT_FALSE(url_loader_client_.has_received_response());
+ ASSERT_FALSE(url_loader_client_.has_received_redirect());
+ url_loader_client_.RunUntilRedirectReceived();
+
+ ASSERT_FALSE(url_loader_client_.has_received_response());
+ ASSERT_TRUE(url_loader_client_.has_received_redirect());
+ EXPECT_EQ(302, url_loader_client_.redirect_info().status_code);
+
+ EXPECT_EQ(1, resource_controller_.num_resume_calls());
+ handler_->FollowRedirect();
+ EXPECT_EQ(2, resource_controller_.num_resume_calls());
+
+ // Give the final response.
+ defer = false;
+ ASSERT_TRUE(handler_->OnResponseStarted(response.get(), &defer));
+ ASSERT_FALSE(defer);
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
+ handler_->OnResponseCompleted(status, &defer);
+ ASSERT_FALSE(defer);
+
+ ASSERT_FALSE(url_loader_client_.has_received_completion());
+ url_loader_client_.RunUntilComplete();
+
+ ASSERT_TRUE(url_loader_client_.has_received_response());
+ ASSERT_TRUE(url_loader_client_.has_received_completion());
+ EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code);
+}
+
+TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
+ MalformedFollowRedirectRequest) {
+ handler_->FollowRedirect();
+
+ EXPECT_TRUE(handler_->has_received_bad_message());
+ EXPECT_EQ(0, resource_controller_.num_resume_calls());
+}
+
// Typically ResourceHandler methods are called in this order.
TEST_P(
MojoAsyncResourceHandlerWithAllocationSizeTest,
diff --git a/chromium/content/browser/loader/navigation_resource_handler.cc b/chromium/content/browser/loader/navigation_resource_handler.cc
index 76a5d8898db..dc73b854bea 100644
--- a/chromium/content/browser/loader/navigation_resource_handler.cc
+++ b/chromium/content/browser/loader/navigation_resource_handler.cc
@@ -14,7 +14,6 @@
#include "content/browser/resource_context_impl.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
-#include "content/common/security_style_util.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -32,9 +31,7 @@ void NavigationResourceHandler::GetSSLStatusForRequest(
int child_id,
SSLStatus* ssl_status) {
DCHECK(ssl_info.cert);
- *ssl_status = SSLStatus(GetSecurityStyleForResource(
- url, !!ssl_info.cert, ssl_info.cert_status),
- ssl_info.cert, ssl_info);
+ *ssl_status = SSLStatus(ssl_info);
}
NavigationResourceHandler::NavigationResourceHandler(
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.cc b/chromium/content/browser/loader/navigation_resource_throttle.cc
index 46e901fd694..e8f9e6ed25b 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.cc
+++ b/chromium/content/browser/loader/navigation_resource_throttle.cc
@@ -15,6 +15,8 @@
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/navigation_resource_handler.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_data.h"
@@ -38,6 +40,9 @@ namespace {
// NavigationHandle.
bool g_ui_checks_always_succeed = false;
+// Used in unit tests to transfer all navigations.
+bool g_force_transfer = false;
+
typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
UIChecksPerformedCallback;
@@ -76,11 +81,9 @@ NavigationHandleImpl* FindNavigationHandle(
}
NavigationHandleImpl* navigation_handle =
- render_frame_host->frame_tree_node()
- ->navigator()
- ->GetNavigationHandleForFrameHost(render_frame_host);
+ render_frame_host->navigation_handle();
if (!navigation_handle) {
- SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
+ SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
return nullptr;
}
return navigation_handle;
@@ -118,7 +121,8 @@ void CheckWillRedirectRequestOnUIThread(
const std::string& new_method,
const GURL& new_referrer_url,
bool new_is_external_protocol,
- scoped_refptr<net::HttpResponseHeaders> headers) {
+ scoped_refptr<net::HttpResponseHeaders> headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
NavigationHandleImpl* navigation_handle =
FindNavigationHandle(render_process_id, render_frame_host_id, callback);
@@ -130,7 +134,8 @@ void CheckWillRedirectRequestOnUIThread(
->FilterURL(false, &new_validated_url);
navigation_handle->WillRedirectRequest(
new_validated_url, new_method, new_referrer_url, new_is_external_protocol,
- headers, base::Bind(&SendCheckResultToIOThread, callback));
+ headers, connection_info,
+ base::Bind(&SendCheckResultToIOThread, callback));
}
void WillProcessResponseOnUIThread(
@@ -138,9 +143,20 @@ void WillProcessResponseOnUIThread(
int render_process_id,
int render_frame_host_id,
scoped_refptr<net::HttpResponseHeaders> headers,
+ net::HttpResponseInfo::ConnectionInfo connection_info,
const SSLStatus& ssl_status,
+ const GlobalRequestID& request_id,
+ bool should_replace_current_entry,
+ bool is_download,
+ bool is_stream,
+ const base::Closure& transfer_callback,
std::unique_ptr<NavigationData> navigation_data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (g_force_transfer) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, transfer_callback);
+ }
+
NavigationHandleImpl* navigation_handle =
FindNavigationHandle(render_process_id, render_frame_host_id, callback);
if (!navigation_handle)
@@ -153,7 +169,8 @@ void WillProcessResponseOnUIThread(
RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
DCHECK(render_frame_host);
navigation_handle->WillProcessResponse(
- render_frame_host, headers, ssl_status,
+ render_frame_host, headers, connection_info, ssl_status, request_id,
+ should_replace_current_entry, is_download, is_stream, transfer_callback,
base::Bind(&SendCheckResultToIOThread, callback));
}
@@ -166,6 +183,8 @@ NavigationResourceThrottle::NavigationResourceThrottle(
: request_(request),
resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate),
request_context_type_(request_context_type),
+ in_cross_site_transition_(false),
+ on_transfer_done_result_(NavigationThrottle::DEFER),
weak_ptr_factory_(this) {}
NavigationResourceThrottle::~NavigationResourceThrottle() {}
@@ -238,13 +257,15 @@ void NavigationResourceThrottle::WillRedirectRequest(
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));
+ new_is_external_protocol, response_headers,
+ request_->response_info().connection_info));
*defer = true;
}
void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
if (!info)
return;
@@ -274,6 +295,9 @@ void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
UIChecksPerformedCallback callback =
base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
weak_ptr_factory_.GetWeakPtr());
+ base::Closure transfer_callback =
+ base::Bind(&NavigationResourceThrottle::InitiateTransfer,
+ weak_ptr_factory_.GetWeakPtr());
SSLStatus ssl_status;
if (request_->ssl_info().cert.get()) {
@@ -284,7 +308,11 @@ void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&WillProcessResponseOnUIThread, callback, render_process_id,
- render_frame_id, response_headers, ssl_status,
+ 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;
}
@@ -298,9 +326,20 @@ void NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(
g_ui_checks_always_succeed = ui_checks_always_succeed;
}
+void NavigationResourceThrottle::set_force_transfer_for_testing(
+ bool force_transfer) {
+ g_force_transfer = force_transfer;
+}
+
void NavigationResourceThrottle::OnUIChecksPerformed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_NE(NavigationThrottle::DEFER, result);
+ if (in_cross_site_transition_) {
+ on_transfer_done_result_ = result;
+ return;
+ }
+
if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
controller()->CancelAndIgnore();
} else if (result == NavigationThrottle::CANCEL) {
@@ -312,4 +351,28 @@ void NavigationResourceThrottle::OnUIChecksPerformed(
}
}
+void NavigationResourceThrottle::InitiateTransfer() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ in_cross_site_transition_ = true;
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(
+ info->GetGlobalRequestID(),
+ base::Bind(&NavigationResourceThrottle::OnTransferComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void NavigationResourceThrottle::OnTransferComplete() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(in_cross_site_transition_);
+ in_cross_site_transition_ = false;
+
+ // If the results of the checks on the UI thread are known, unblock the
+ // navigation. Otherwise, wait until the callback has executed.
+ if (on_transfer_done_result_ != NavigationThrottle::DEFER) {
+ OnUIChecksPerformed(on_transfer_done_result_);
+ on_transfer_done_result_ = NavigationThrottle::DEFER;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.h b/chromium/content/browser/loader/navigation_resource_throttle.h
index e85a1fb9a09..a9685e347c7 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.h
+++ b/chromium/content/browser/loader/navigation_resource_throttle.h
@@ -42,12 +42,23 @@ class NavigationResourceThrottle : public ResourceThrottle {
CONTENT_EXPORT static void set_ui_checks_always_succeed_for_testing(
bool ui_checks_always_succeed);
+ // Used in unit tests to make all navigations transfer.
+ CONTENT_EXPORT static void set_force_transfer_for_testing(
+ bool force_transfer);
+
private:
void OnUIChecksPerformed(NavigationThrottle::ThrottleCheckResult result);
+ // Used in transfer navigations.
+ void InitiateTransfer();
+ void OnTransferComplete();
+
net::URLRequest* request_;
ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate_;
RequestContextType request_context_type_;
+ bool in_cross_site_transition_;
+ NavigationThrottle::ThrottleCheckResult on_transfer_done_result_;
+
base::WeakPtrFactory<NavigationResourceThrottle> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationResourceThrottle);
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index d4494aadca7..a97e0d728b6 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -17,7 +17,6 @@ class NavigationUIData;
class NavigationURLLoaderDelegate;
class NavigationURLLoaderFactory;
class ServiceWorkerNavigationHandle;
-struct CommonNavigationParams;
struct NavigationRequestInfo;
// PlzNavigate: The navigation logic's UI thread entry point into the resource
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 786634c349e..dd55af60123 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -12,18 +12,15 @@
#include "content/browser/loader/navigation_url_loader_impl.h"
namespace net {
-class URLRequest;
struct RedirectInfo;
}
namespace content {
-class FrameTreeNode;
class NavigationResourceHandler;
class NavigationData;
class ResourceContext;
class ResourceHandler;
-class ResourceRequestBody;
class ServiceWorkerNavigationHandleCore;
class StreamHandle;
struct ResourceResponse;
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 89604bb33ba..a0b61b98c6b 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -112,7 +112,8 @@ class NavigationURLLoaderTest : public testing::Test {
common_params.url = url;
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, begin_params, url,
- url::Origin(url), true, false, false, -1));
+ url::Origin(url), true, false, false, -1,
+ false, false));
return NavigationURLLoader::Create(browser_context_.get(),
std::move(request_info), nullptr,
diff --git a/chromium/content/browser/loader/reload_cache_control_browsertest.cc b/chromium/content/browser/loader/reload_cache_control_browsertest.cc
index 362bff46039..8999d37b199 100644
--- a/chromium/content/browser/loader/reload_cache_control_browsertest.cc
+++ b/chromium/content/browser/loader/reload_cache_control_browsertest.cc
@@ -6,8 +6,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/feature_list.h"
#include "base/files/file_path.h"
+#include "base/test/scoped_feature_list.h"
#include "content/public/common/content_features.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -45,11 +45,8 @@ class ReloadCacheControlBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
// TODO(toyoshim): Tests in this file depend on current reload behavior,
// and should be modified when we enable the new reload behavior.
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- std::string(), features::kNonValidatingReloadOnNormalReload.name);
- base::FeatureList::SetInstance(std::move(feature_list));
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kNonValidatingReloadOnNormalReload);
SetUpTestServerOnMainThread();
}
@@ -80,6 +77,8 @@ class ReloadCacheControlBrowserTest : public ContentBrowserTest {
request_log_.push_back(log);
}
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(ReloadCacheControlBrowserTest);
};
@@ -90,15 +89,14 @@ class ReloadCacheControlWithAnExperimentBrowserTest
~ReloadCacheControlWithAnExperimentBrowserTest() override = default;
void SetUpOnMainThread() override {
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- features::kNonValidatingReloadOnNormalReload.name, std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kNonValidatingReloadOnNormalReload);
SetUpTestServerOnMainThread();
}
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(ReloadCacheControlWithAnExperimentBrowserTest);
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index e69f948ee47..b47f3572a81 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
@@ -16,6 +17,7 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/download/download_manager_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -238,6 +240,52 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
ASSERT_FALSE(got_downloads());
}
+namespace {
+
+// Responses with a HungResponse for the specified URL to hang on the request,
+// and cancells all requests from specifield |child_id|.
+std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
+ const std::string& relative_url,
+ int child_id,
+ const net::test_server::HttpRequest& request) {
+ if (request.relative_url != relative_url)
+ return nullptr;
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ child_id));
+
+ return base::MakeUnique<net::test_server::HungResponse>();
+}
+
+} // namespace
+
+// Tests the case where the request is cancelled by a layer above the
+// URLRequest, which passes the error on ResourceLoader teardown, rather than in
+// response to call to AsyncResourceHandler::OnResponseComplete.
+IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
+ SyncXMLHttpRequest_Cancelled) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WaitForLoadStop(shell()->web_contents());
+
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&CancelOnRequest, "/hung",
+ shell()->web_contents()->GetRenderProcessHost()->GetID()));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "/sync_xmlhttprequest_cancelled.html"));
+
+ int status_code = -1;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ shell(), "window.domAutomationController.send(getErrorCode());",
+ &status_code));
+
+ // 19 is the value of NETWORK_ERROR on DOMException.
+ EXPECT_EQ(19, status_code);
+}
+
// Flaky everywhere. http://crbug.com/130404
// Tests that onunload is run for cross-site requests. (Bug 1114994)
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
@@ -297,6 +345,10 @@ std::unique_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
// If this flakes use http://crbug.com/80596.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CrossSiteNoUnloadOn204) {
+ const char kNoContentPath[] = "/nocontent";
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&NoContentResponseHandler, kNoContentPath));
+
ASSERT_TRUE(embedded_test_server()->Start());
// Start with a URL that sets a cookie in its unload handler.
@@ -304,9 +356,6 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CheckTitleTest(url, "set cookie on unload");
// Navigate to a cross-site URL that returns a 204 No Content response.
- const char kNoContentPath[] = "/nocontent";
- embedded_test_server()->RegisterRequestHandler(
- base::Bind(&NoContentResponseHandler, kNoContentPath));
NavigateToURL(shell(), embedded_test_server()->GetURL(kNoContentPath));
// Check that the unload cookie was not set.
@@ -480,9 +529,9 @@ std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
// Test that we update the cookie policy URLs correctly when transferring
// navigations.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CookiePolicy) {
- ASSERT_TRUE(embedded_test_server()->Start());
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleRedirectRequest, "/redirect?"));
+ ASSERT_TRUE(embedded_test_server()->Start());
std::string set_cookie_url(base::StringPrintf(
"http://localhost:%u/set_cookie.html", embedded_test_server()->port()));
@@ -755,11 +804,11 @@ namespace {
struct RequestDataForDelegate {
const GURL url;
const GURL first_party;
- const url::Origin initiator;
+ const base::Optional<url::Origin> initiator;
RequestDataForDelegate(const GURL& url,
const GURL& first_party,
- const url::Origin initiator)
+ const base::Optional<url::Origin>& initiator)
: url(url), first_party(first_party), initiator(initiator) {}
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 8cc50c6f058..4117eae4cdc 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -32,7 +32,7 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/bad_message.h"
@@ -44,7 +44,6 @@
#include "content/browser/frame_host/navigator.h"
#include "content/browser/loader/async_resource_handler.h"
#include "content/browser/loader/async_revalidation_manager.h"
-#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/intercepting_resource_handler.h"
#include "content/browser/loader/loader_delegate.h"
@@ -55,8 +54,10 @@
#include "content/browser/loader/navigation_url_loader_impl_core.h"
#include "content/browser/loader/power_save_block_resource_throttle.h"
#include "content/browser/loader/redirect_to_file_resource_handler.h"
+#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/loader/resource_scheduler.h"
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/loader/sync_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
@@ -64,6 +65,7 @@
#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/foreign_fetch_request_handler.h"
#include "content/browser/service_worker/link_header_support.h"
+#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
@@ -96,10 +98,10 @@
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/base/request_priority.h"
#include "net/base/upload_data_stream.h"
#include "net/cert/cert_status_flags.h"
#include "net/cookies/cookie_monster.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/ssl/client_cert_store.h"
@@ -113,12 +115,15 @@
#include "storage/browser/blob/shareable_file_reference.h"
#include "storage/browser/fileapi/file_permission_policy.h"
#include "storage/browser/fileapi/file_system_context.h"
+#include "url/third_party/mozilla/url_parse.h"
#include "url/url_constants.h"
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
using storage::ShareableFileReference;
+using SyncLoadResultCallback =
+ content::ResourceDispatcherHostImpl::SyncLoadResultCallback;
// ----------------------------------------------------------------------------
@@ -221,15 +226,15 @@ bool IsDetachableResourceType(ResourceType type) {
}
// Aborts a request before an URLRequest has actually been created.
-void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
- IPC::Message* sync_result,
- int request_id,
- mojom::URLLoaderClientPtr url_loader_client) {
- if (sync_result) {
+void AbortRequestBeforeItStarts(
+ ResourceMessageFilter* filter,
+ const SyncLoadResultCallback& sync_result_handler,
+ int request_id,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client) {
+ if (sync_result_handler) {
SyncLoadResult result;
result.error_code = net::ERR_ABORTED;
- ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result);
- filter->Send(sync_result);
+ sync_result_handler.Run(&result);
} else {
// Tell the renderer that this request was disallowed.
ResourceRequestCompletionStatus request_complete_data;
@@ -261,9 +266,13 @@ void SetReferrerForRequest(net::URLRequest* request, const Referrer& referrer) {
net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
switch (referrer.policy) {
case blink::WebReferrerPolicyAlways:
+ net_referrer_policy = net::URLRequest::NEVER_CLEAR_REFERRER;
+ break;
case blink::WebReferrerPolicyNever:
+ net_referrer_policy = net::URLRequest::NO_REFERRER;
+ break;
case blink::WebReferrerPolicyOrigin:
- net_referrer_policy = net::URLRequest::NEVER_CLEAR_REFERRER;
+ net_referrer_policy = net::URLRequest::ORIGIN;
break;
case blink::WebReferrerPolicyNoReferrerWhenDowngrade:
net_referrer_policy =
@@ -414,6 +423,22 @@ void NotifyForEachFrameFromUI(
base::Passed(std::move(routing_ids))));
}
+// Sends back the result of a synchronous loading result to the renderer through
+// Chrome IPC.
+void HandleSyncLoadResult(base::WeakPtr<ResourceMessageFilter> filter,
+ std::unique_ptr<IPC::Message> sync_result,
+ const SyncLoadResult* result) {
+ if (!filter)
+ return;
+
+ if (result) {
+ ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result.get(), *result);
+ } else {
+ sync_result->set_reply_error();
+ }
+ filter->Send(sync_result.release());
+}
+
} // namespace
ResourceDispatcherHostImpl::LoadInfo::LoadInfo() {}
@@ -728,10 +753,7 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
if (job_factory->IsHandledURL(url))
return false;
- return delegate_->HandleExternalProtocol(
- url, info->GetChildID(), info->GetWebContentsGetterForRequest(),
- info->IsMainFrame(), info->GetPageTransition(), info->HasUserGesture(),
- info->GetContext());
+ return delegate_->HandleExternalProtocol(url, info);
}
void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
@@ -909,7 +931,7 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
}
if (loader->request()->url().SchemeIsCryptographic()) {
- if (loader->request()->url().host() == "www.google.com") {
+ if (loader->request()->url().host_piece() == "www.google.com") {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.ErrorCodesForHTTPSGoogleMainFrame2",
-loader->request()->status().error());
}
@@ -995,7 +1017,6 @@ bool ResourceDispatcherHostImpl::OnMessageReceived(
IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad)
IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile,
OnReleaseDownloadedFile)
- IPC_MESSAGE_HANDLER(ResourceHostMsg_DataDownloaded_ACK, OnDataDownloadedACK)
IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest)
IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, OnDidChangePriority)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -1009,10 +1030,11 @@ bool ResourceDispatcherHostImpl::OnMessageReceived(
GlobalRequestID id(filter_->child_id(), request_id);
DelegateMap::iterator it = delegate_map_.find(id);
if (it != delegate_map_.end()) {
- base::ObserverList<ResourceMessageDelegate>::Iterator del_it(it->second);
- ResourceMessageDelegate* delegate;
- while (!handled && (delegate = del_it.GetNext()) != NULL) {
- handled = delegate->OnMessageReceived(message);
+ for (auto& delegate : *it->second) {
+ if (delegate.OnMessageReceived(message)) {
+ handled = true;
+ break;
+ }
}
}
@@ -1037,8 +1059,8 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
int routing_id,
int request_id,
const ResourceRequest& request_data,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client) {
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client) {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
@@ -1059,7 +1081,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
request_data.render_frame_id,
request_data.url));
}
- BeginRequest(request_id, request_data, NULL, routing_id,
+ BeginRequest(request_id, request_data, SyncLoadResultCallback(), routing_id,
std::move(mojo_request), std::move(url_loader_client));
}
@@ -1074,7 +1096,10 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
void ResourceDispatcherHostImpl::OnSyncLoad(int request_id,
const ResourceRequest& request_data,
IPC::Message* sync_result) {
- BeginRequest(request_id, request_data, sync_result, sync_result->routing_id(),
+ SyncLoadResultCallback callback = base::Bind(
+ &HandleSyncLoadResult, filter_->GetWeakPtr(),
+ base::Passed(WrapUnique(sync_result)));
+ BeginRequest(request_id, request_data, callback, sync_result->routing_id(),
nullptr, nullptr);
}
@@ -1145,11 +1170,8 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
DelegateMap::iterator it = delegate_map_.find(old_request_id);
if (it != delegate_map_.end()) {
// Tell each delegate that the request ID has changed.
- base::ObserverList<ResourceMessageDelegate>::Iterator del_it(it->second);
- ResourceMessageDelegate* delegate;
- while ((delegate = del_it.GetNext()) != NULL) {
- delegate->set_request_id(new_request_id);
- }
+ for (auto& delegate : *it->second)
+ delegate.set_request_id(new_request_id);
// Now store the observer list under the new request ID.
delegate_map_[new_request_id] = delegate_map_[old_request_id];
delegate_map_.erase(old_request_id);
@@ -1173,18 +1195,66 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
child_id, request_data.service_worker_provider_id);
}
}
+}
+
+void ResourceDispatcherHostImpl::CompleteTransfer(
+ int request_id,
+ const ResourceRequest& request_data,
+ int route_id) {
+ // Caller should ensure that |request_data| is associated with a transfer.
+ DCHECK(request_data.transferred_request_child_id != -1 ||
+ request_data.transferred_request_request_id != -1);
+
+ bool is_navigational_request =
+ request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME ||
+ request_data.resource_type == RESOURCE_TYPE_SUB_FRAME;
+ if (!is_navigational_request) {
+ // Transfers apply only to navigational requests - the renderer seems to
+ // have sent bogus IPC data.
+ bad_message::ReceivedBadMessage(
+ filter_, bad_message::RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST);
+ return;
+ }
- // We should have a CrossSiteResourceHandler to finish the transfer.
- DCHECK(info->cross_site_handler());
+ // Attempt to find a loader associated with the deferred transfer request.
+ LoaderMap::iterator it = pending_loaders_.find(
+ GlobalRequestID(request_data.transferred_request_child_id,
+ request_data.transferred_request_request_id));
+ if (it == pending_loaders_.end()) {
+ // Renderer sent transferred_request_request_id and/or
+ // transferred_request_child_id that doesn't have a corresponding entry on
+ // the browser side.
+ // TODO(lukasza): https://crbug.com/659613: Need to understand the scenario
+ // that can lead here (and then attempt to reintroduce a renderer kill
+ // below).
+ return;
+ }
+ ResourceLoader* pending_loader = it->second.get();
+
+ if (!pending_loader->is_transferring()) {
+ // Renderer sent transferred_request_request_id and/or
+ // transferred_request_child_id that doesn't correspond to an actually
+ // transferring loader on the browser side.
+ base::debug::Alias(pending_loader);
+ bad_message::ReceivedBadMessage(filter_,
+ bad_message::RDH_REQUEST_NOT_TRANSFERRING);
+ return;
+ }
+
+ // If the request is transferring to a new process, we can update our
+ // state and let it resume with its existing ResourceHandlers.
+ UpdateRequestForTransfer(filter_->child_id(), route_id, request_id,
+ request_data, it);
+ pending_loader->CompleteTransfer();
}
void ResourceDispatcherHostImpl::BeginRequest(
int request_id,
const ResourceRequest& request_data,
- IPC::Message* sync_result, // only valid for sync
+ const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client) {
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client) {
int process_type = filter_->process_type();
int child_id = filter_->child_id();
@@ -1222,24 +1292,12 @@ void ResourceDispatcherHostImpl::BeginRequest(
// If the request that's coming in is being transferred from another process,
// we want to reuse and resume the old loader rather than start a new one.
- LoaderMap::iterator it = pending_loaders_.find(
- GlobalRequestID(request_data.transferred_request_child_id,
- request_data.transferred_request_request_id));
- if (it != pending_loaders_.end()) {
+ if (request_data.transferred_request_child_id != -1 ||
+ request_data.transferred_request_request_id != -1) {
// TODO(yhirano): Make mojo work for this case.
DCHECK(!url_loader_client);
- // If the request is transferring to a new process, we can update our
- // state and let it resume with its existing ResourceHandlers.
- if (it->second->is_transferring()) {
- ResourceLoader* deferred_loader = it->second.get();
- UpdateRequestForTransfer(child_id, route_id, request_id,
- request_data, it);
- deferred_loader->CompleteTransfer();
- } else {
- bad_message::ReceivedBadMessage(
- filter_, bad_message::RDH_REQUEST_NOT_TRANSFERRING);
- }
+ CompleteTransfer(request_id, request_data, route_id);
return;
}
@@ -1256,7 +1314,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
if (is_shutdown_ ||
!ShouldServiceRequest(process_type, child_id, request_data, headers,
filter_, resource_context)) {
- AbortRequestBeforeItStarts(filter_, sync_result, request_id,
+ AbortRequestBeforeItStarts(filter_, sync_result_handler, request_id,
std::move(url_loader_client));
return;
}
@@ -1281,33 +1339,33 @@ void ResourceDispatcherHostImpl::BeginRequest(
it.name(), it.value(), child_id, resource_context,
base::Bind(&ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
base::Unretained(this), request_id, request_data,
- sync_result, route_id, headers,
+ sync_result_handler, route_id, headers,
base::Passed(std::move(mojo_request)),
base::Passed(std::move(url_loader_client))));
return;
}
}
}
- ContinuePendingBeginRequest(request_id, request_data, sync_result, route_id,
- headers, std::move(mojo_request),
+ ContinuePendingBeginRequest(request_id, request_data, sync_result_handler,
+ route_id, headers, std::move(mojo_request),
std::move(url_loader_client), true, 0);
}
void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
int request_id,
const ResourceRequest& request_data,
- IPC::Message* sync_result, // only valid for sync
+ const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
const net::HttpRequestHeaders& headers,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client,
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client,
bool continue_request,
int error_code) {
if (!continue_request) {
// TODO(ananta): Find a way to specify the right error code here. Passing
// in a non-content error code is not safe.
bad_message::ReceivedBadMessage(filter_, bad_message::RDH_ILLEGAL_ORIGIN);
- AbortRequestBeforeItStarts(filter_, sync_result, request_id,
+ AbortRequestBeforeItStarts(filter_, sync_result_handler, request_id,
std::move(url_loader_client));
return;
}
@@ -1330,7 +1388,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
request_data.url,
request_data.resource_type,
resource_context)) {
- AbortRequestBeforeItStarts(filter_, sync_result, request_id,
+ AbortRequestBeforeItStarts(filter_, sync_result_handler, request_id,
std::move(url_loader_client));
return;
}
@@ -1352,6 +1410,12 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->set_first_party_for_cookies(
request_data.first_party_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:
+ // browser-initiated ones).
+ DCHECK(request_data.request_initiator.has_value() ||
+ request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME);
new_request->set_initiator(request_data.request_initiator);
if (request_data.originated_from_service_worker) {
@@ -1403,7 +1467,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
bool allow_download = request_data.allow_download &&
IsResourceTypeFrame(request_data.resource_type);
bool do_not_prompt_for_login = request_data.do_not_prompt_for_login;
- bool is_sync_load = sync_result != NULL;
+ bool is_sync_load = !!sync_result_handler;
// Raw headers are sensitive, as they include Cookie/Set-Cookie, so only
// allow requesting them if requester has ReadRawCookies permission.
@@ -1515,8 +1579,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
request_data.should_reset_appcache);
std::unique_ptr<ResourceHandler> handler(CreateResourceHandler(
- new_request.get(), request_data, sync_result, route_id, process_type,
- child_id, resource_context, std::move(mojo_request),
+ new_request.get(), request_data, sync_result_handler, route_id,
+ process_type, child_id, resource_context, std::move(mojo_request),
std::move(url_loader_client)));
if (handler)
@@ -1527,20 +1591,20 @@ std::unique_ptr<ResourceHandler>
ResourceDispatcherHostImpl::CreateResourceHandler(
net::URLRequest* request,
const ResourceRequest& request_data,
- IPC::Message* sync_result,
+ const SyncLoadResultCallback& sync_result_handler,
int route_id,
int process_type,
int child_id,
ResourceContext* resource_context,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client) {
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client) {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/456331 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456331 ResourceDispatcherHostImpl::CreateResourceHandler"));
// Construct the IPC resource handler.
std::unique_ptr<ResourceHandler> handler;
- if (sync_result) {
+ if (sync_result_handler) {
// download_to_file is not supported for synchronous requests.
if (request_data.download_to_file) {
bad_message::ReceivedBadMessage(filter_, bad_message::RDH_BAD_DOWNLOAD);
@@ -1549,7 +1613,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
DCHECK(!mojo_request.is_pending());
DCHECK(!url_loader_client);
- handler.reset(new SyncResourceHandler(request, sync_result, this));
+ handler.reset(new SyncResourceHandler(request, sync_result_handler, this));
} else {
if (mojo_request.is_pending()) {
handler.reset(new MojoAsyncResourceHandler(request, this,
@@ -1569,8 +1633,9 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
bool start_detached = request_data.download_to_network_cache_only;
// Prefetches and <a ping> requests outlive their child process.
- if (!sync_result && (start_detached ||
- IsDetachableResourceType(request_data.resource_type))) {
+ if (!sync_result_handler &&
+ (start_detached ||
+ IsDetachableResourceType(request_data.resource_type))) {
std::unique_ptr<DetachableResourceHandler> detachable_handler =
base::MakeUnique<DetachableResourceHandler>(
request,
@@ -1581,28 +1646,6 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
handler = std::move(detachable_handler);
}
- // PlzNavigate: If using --enable-browser-side-navigation, the
- // CrossSiteResourceHandler is not needed. This codepath is not used for the
- // actual navigation request, but only the subsequent blob URL load. This does
- // not require request transfers.
- if (!IsBrowserSideNavigationEnabled()) {
- // Install a CrossSiteResourceHandler for all main frame requests. This will
- // check whether a transfer is required and, if so, pause for the UI thread
- // to drive the transfer.
- bool is_swappable_navigation =
- request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME;
- // If out-of-process iframes are possible, then all subframe requests need
- // to go through the CrossSiteResourceHandler to enforce the site isolation
- // policy.
- if (!is_swappable_navigation &&
- SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
- is_swappable_navigation =
- request_data.resource_type == RESOURCE_TYPE_SUB_FRAME;
- }
- if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER)
- handler.reset(new CrossSiteResourceHandler(std::move(handler), request));
- }
-
return AddStandardHandlers(
request, request_data.resource_type, resource_context,
request_data.fetch_request_context_type, filter_->appcache_service(),
@@ -1725,10 +1768,6 @@ void ResourceDispatcherHostImpl::OnDidChangePriority(
intra_priority_value);
}
-void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) {
- // TODO(michaeln): maybe throttle DataDownloaded messages
-}
-
void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
int child_id, int request_id, const base::FilePath& file_path) {
scoped_refptr<ShareableFileReference> reference =
@@ -1770,26 +1809,8 @@ bool ResourceDispatcherHostImpl::Send(IPC::Message* message) {
return false;
}
-// Note that this cancel is subtly different from the other
-// CancelRequest methods in this file, which also tear down the loader.
void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) {
- int child_id = filter_->child_id();
-
- // When the old renderer dies, it sends a message to us to cancel its
- // requests.
- if (IsTransferredNavigation(GlobalRequestID(child_id, request_id)))
- return;
-
- ResourceLoader* loader = GetLoader(child_id, request_id);
-
- // It is possible that the request has been completed and removed from the
- // loader queue but the client has not processed the request completed message
- // before issuing a cancel. This happens frequently for beacons which are
- // canceled in the response received handler.
- if (!loader)
- return;
-
- loader->CancelRequest(true);
+ CancelRequestFromRenderer(GlobalRequestID(filter_->child_id(), request_id));
}
ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
@@ -1799,17 +1820,12 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
bool download,
ResourceContext* context) {
return new ResourceRequestInfoImpl(
- PROCESS_TYPE_RENDERER,
- child_id,
- render_view_route_id,
+ PROCESS_TYPE_RENDERER, child_id, render_view_route_id,
-1, // frame_tree_node_id
- 0,
- request_id_,
- render_frame_route_id,
- false, // is_main_frame
- false, // parent_is_main_frame
- RESOURCE_TYPE_SUB_RESOURCE,
- ui::PAGE_TRANSITION_LINK,
+ 0, MakeRequestID(), render_frame_route_id,
+ false, // is_main_frame
+ false, // parent_is_main_frame
+ RESOURCE_TYPE_SUB_RESOURCE, ui::PAGE_TRANSITION_LINK,
false, // should_replace_current_entry
download, // is_download
false, // is_stream
@@ -1818,8 +1834,7 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false, // enable_load_timing
false, // enable_upload_progress
false, // do_not_prompt_for_login
- blink::WebReferrerPolicyDefault,
- blink::WebPageVisibilityStateVisible,
+ blink::WebReferrerPolicyDefault, blink::WebPageVisibilityStateVisible,
context,
base::WeakPtr<ResourceMessageFilter>(), // filter
false, // report_raw_headers
@@ -1848,8 +1863,8 @@ void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
const GlobalRequestID& id,
- const scoped_refptr<ResourceResponse>& response) {
- GetLoader(id)->MarkAsTransferring(response);
+ const base::Closure& on_transfer_complete_callback) {
+ GetLoader(id)->MarkAsTransferring(on_transfer_complete_callback);
}
void ResourceDispatcherHostImpl::CancelTransferringNavigation(
@@ -2083,7 +2098,21 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
ResourceType resource_type = info.is_main_frame ?
RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME;
- if (is_shutdown_ ||
+ // Do not allow browser plugin guests to navigate to non-web URLs, since they
+ // cannot swap processes or grant bindings. Do not check external protocols
+ // here because they're checked in
+ // ChromeResourceDispatcherHostDelegate::HandleExternalProtocol.
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ bool is_external_protocol =
+ !resource_context->GetRequestContext()->job_factory()->IsHandledURL(
+ info.common_params.url);
+ bool non_web_url_in_guest =
+ info.is_for_guests_only &&
+ !policy->IsWebSafeScheme(info.common_params.url.scheme()) &&
+ !is_external_protocol;
+
+ if (is_shutdown_ || non_web_url_in_guest ||
// TODO(davidben): Check ShouldServiceRequest here. This is important; it
// needs to be checked relative to the child that /requested/ the
// navigation. It's where file upload checks, etc., come in.
@@ -2148,8 +2177,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get()));
}
- request_id_--;
-
// Make extra info and read footer (contains request ID).
//
// TODO(davidben): Associate the request with the FrameTreeNode and/or tab so
@@ -2160,7 +2187,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
-1, // route_id
info.frame_tree_node_id,
-1, // request_data.origin_pid,
- request_id_,
+ MakeRequestID(),
-1, // request_data.render_frame_id,
info.is_main_frame, info.parent_is_main_frame, resource_type,
info.common_params.transition,
@@ -2179,7 +2206,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// same mechanism as the cookie one.
blink::WebPageVisibilityStateVisible, resource_context,
base::WeakPtr<ResourceMessageFilter>(), // filter
- false, // request_data.report_raw_headers
+ info.report_raw_headers,
true, // is_async
IsUsingLoFi(info.common_params.lofi_state, delegate_, *new_request,
resource_context, info.is_main_frame),
@@ -2197,6 +2224,11 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
false); // initiated_in_secure_context
extra_info->set_navigation_ui_data(std::move(navigation_ui_data));
+ if (service_worker_handle_core) {
+ extra_info->set_service_worker_context(
+ service_worker_handle_core->context_wrapper());
+ }
+
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
@@ -2255,8 +2287,8 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
int routing_id,
int request_id,
const ResourceRequest& request,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client,
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client,
ResourceMessageFilter* filter) {
filter_ = filter;
OnRequestResourceInternal(routing_id, request_id, request,
@@ -2265,16 +2297,32 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
filter_ = nullptr;
}
+void ResourceDispatcherHostImpl::OnSyncLoadWithMojo(
+ int routing_id,
+ int request_id,
+ const ResourceRequest& request_data,
+ ResourceMessageFilter* filter,
+ const SyncLoadResultCallback& result_handler) {
+ filter_ = filter;
+ BeginRequest(request_id, request_data, result_handler, routing_id,
+ nullptr, nullptr);
+ filter_ = nullptr;
+}
+
// static
int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
net::URLRequest* request) {
// The following fields should be a minor size contribution (experimentally
// on the order of 100). However since they are variable length, it could
// in theory be a sizeable contribution.
- int strings_cost = request->extra_request_headers().ToString().size() +
- request->original_url().spec().size() +
- request->referrer().size() +
- request->method().size();
+ int strings_cost = 0;
+ for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers());
+ it.GetNext();) {
+ strings_cost += it.name().length() + it.value().length();
+ }
+ strings_cost +=
+ request->original_url().parsed_for_possibly_invalid_spec().Length() +
+ request->referrer().size() + request->method().size();
// Note that this expression will typically be dominated by:
// |kAvgBytesPerOutstandingRequest|.
@@ -2345,8 +2393,6 @@ void ResourceDispatcherHostImpl::InitializeURLRequest(
SetReferrerForRequest(request, referrer);
- request_id_--;
-
ResourceRequestInfoImpl* info =
CreateRequestInfo(render_process_host_id, render_view_routing_id,
render_frame_routing_id, is_download, context);
@@ -2392,6 +2438,30 @@ void ResourceDispatcherHostImpl::BeginURLRequest(
BeginRequestInternal(std::move(request), std::move(handler));
}
+int ResourceDispatcherHostImpl::MakeRequestID() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return --request_id_;
+}
+
+void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
+ GlobalRequestID request_id) {
+ // When the old renderer dies, it sends a message to us to cancel its
+ // requests.
+ if (IsTransferredNavigation(request_id))
+ return;
+
+ ResourceLoader* loader = GetLoader(request_id);
+
+ // It is possible that the request has been completed and removed from the
+ // loader queue but the client has not processed the request completed message
+ // before issuing a cancel. This happens frequently for beacons which are
+ // canceled in the response received handler.
+ if (!loader)
+ return;
+
+ loader->CancelRequest(true);
+}
+
void ResourceDispatcherHostImpl::StartLoading(
ResourceRequestInfoImpl* info,
std::unique_ptr<ResourceLoader> loader) {
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 0ee50dfa24c..655d83fe80a 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -19,16 +19,14 @@
#include <string>
#include <vector>
+#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/browser/download/save_types.h"
#include "content/browser/loader/global_routing_id.h"
-#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_loader_delegate.h"
-#include "content/browser/loader/resource_scheduler.h"
#include "content/common/content_export.h"
#include "content/common/url_loader.mojom.h"
#include "content/public/browser/global_request_id.h"
@@ -37,17 +35,18 @@
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "ipc/ipc_message.h"
-#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/load_states.h"
#include "net/base/request_priority.h"
-#include "net/cookies/canonical_cookie.h"
-#include "net/url_request/url_request.h"
+#include "url/gurl.h"
namespace base {
class FilePath;
+class RepeatingTimer;
}
namespace net {
-class URLRequestJobFactory;
+class URLRequest;
+class HttpRequestHeaders;
}
namespace storage {
@@ -63,20 +62,17 @@ class NavigationUIData;
class RenderFrameHostImpl;
class ResourceContext;
class ResourceDispatcherHostDelegate;
+class ResourceLoader;
class ResourceHandler;
class ResourceMessageDelegate;
class ResourceMessageFilter;
class ResourceRequestInfoImpl;
+class ResourceScheduler;
class ServiceWorkerNavigationHandleCore;
-struct CommonNavigationParams;
struct NavigationRequestInfo;
struct Referrer;
struct ResourceRequest;
-namespace mojom {
-class URLLoader;
-} // namespace mojom
-
using CreateDownloadHandlerIntercept =
base::Callback<std::unique_ptr<ResourceHandler>(net::URLRequest*)>;
@@ -84,6 +80,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
: public ResourceDispatcherHost,
public ResourceLoaderDelegate {
public:
+ // Used to handle the result of SyncLoad IPC. |result| is null if it's
+ // unavailable due to an error.
+ using SyncLoadResultCallback =
+ base::Callback<void(const SyncLoadResult* result)>;
+
// This constructor should be used if we want downloads to work correctly.
// TODO(ananta)
// Work on moving creation of download handlers out of
@@ -144,7 +145,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// resumed by a new process.
void MarkAsTransferredNavigation(
const GlobalRequestID& id,
- const scoped_refptr<ResourceResponse>& response);
+ const base::Closure& on_transfer_complete_callback);
// Cancels a request previously marked as being transferred, for use when a
// navigation was cancelled.
@@ -297,10 +298,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int routing_id,
int request_id,
const ResourceRequest& request,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client,
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client,
ResourceMessageFilter* filter);
+ void OnSyncLoadWithMojo(int routing_id,
+ int request_id,
+ const ResourceRequest& request_data,
+ ResourceMessageFilter* filter,
+ 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.
@@ -330,6 +337,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool is_shutdown() const { return is_shutdown_; }
+ // Creates a new request ID for browser initiated requests. See the comments
+ // of |request_id_| for the details. Must be called on the IO thread.
+ int MakeRequestID();
+
+ // Cancels a request as requested by a renderer. This function is called when
+ // a mojo connection is lost.
+ // Note that this cancel is subtly different from the other CancelRequest
+ // methods in this file, which also tear down the loader.
+ void CancelRequestFromRenderer(GlobalRequestID request_id);
+
private:
friend class ResourceDispatcherHostTest;
@@ -361,6 +378,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
LoadInfo();
LoadInfo(const LoadInfo& other);
~LoadInfo();
+
ResourceRequestInfo::WebContentsGetter web_contents_getter;
GURL url;
net::LoadStateWithParam load_state;
@@ -515,8 +533,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int routing_id,
int request_id,
const ResourceRequest& request_data,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client);
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client);
void OnSyncLoad(int request_id,
const ResourceRequest& request_data,
@@ -532,12 +550,19 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
const ResourceRequest& request_data,
LoaderMap::iterator iter);
- void BeginRequest(int request_id,
- const ResourceRequest& request_data,
- IPC::Message* sync_result, // only valid for sync
- int route_id, // only valid for async
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client);
+ // If |request_data| is for a request being transferred from another process,
+ // then CompleteTransfer method can be used to complete the transfer.
+ void CompleteTransfer(int request_id,
+ const ResourceRequest& request_data,
+ int route_id);
+
+ void BeginRequest(
+ int request_id,
+ const ResourceRequest& request_data,
+ const SyncLoadResultCallback& sync_result_handler, // only valid for sync
+ int route_id,
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client);
// There are requests which need decisions to be made like the following:
// Whether the presence of certain HTTP headers like the Origin header are
@@ -551,11 +576,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void ContinuePendingBeginRequest(
int request_id,
const ResourceRequest& request_data,
- IPC::Message* sync_result, // only valid for sync
+ const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
const net::HttpRequestHeaders& headers,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client,
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client,
bool continue_request,
int error_code);
@@ -564,13 +589,13 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
std::unique_ptr<ResourceHandler> CreateResourceHandler(
net::URLRequest* request,
const ResourceRequest& request_data,
- IPC::Message* sync_result,
+ const SyncLoadResultCallback& sync_result_handler,
int route_id,
int process_type,
int child_id,
ResourceContext* resource_context,
- mojo::InterfaceRequest<mojom::URLLoader> mojo_request,
- mojom::URLLoaderClientPtr url_loader_client);
+ mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderClientAssociatedPtr url_loader_client);
// Wraps |handler| in the standard resource handlers for normal resource
// loading and navigation requests. This adds MimeTypeResourceHandler and
@@ -585,7 +610,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int route_id,
std::unique_ptr<ResourceHandler> handler);
- void OnDataDownloadedACK(int request_id);
void OnCancelRequest(int request_id);
void OnReleaseDownloadedFile(int request_id);
void OnDidChangePriority(int request_id,
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index a4bcf9b425a..8dfae97d5e5 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
@@ -21,13 +20,13 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/navigation_resource_throttle.h"
#include "content/browser/loader/navigation_url_loader.h"
@@ -160,6 +159,7 @@ static ResourceRequest CreateResourceRequest(const char* method,
request.method = std::string(method);
request.url = url;
request.first_party_for_cookies = url; // bypass third-party cookie blocking
+ request.request_initiator = url::Origin(url); // ensure initiator is set
request.referrer_policy = blink::WebReferrerPolicyDefault;
request.load_flags = 0;
request.origin_pid = 0;
@@ -203,6 +203,9 @@ class ResourceIPCAccumulator {
typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages;
void GetClassifiedMessages(ClassifiedMessages* msgs);
+ // Returns the reply of |msg|, which is a synchronous IPC message.
+ const IPC::Message* GetReply(const IPC::Message& msg);
+
private:
std::vector<IPC::Message> messages_;
};
@@ -232,6 +235,17 @@ void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
}
}
+const IPC::Message* ResourceIPCAccumulator::GetReply(const IPC::Message& msg) {
+ for (auto& reply : messages_) {
+ if (!reply.is_reply())
+ continue;
+ if (IPC::SyncMessage::GetMessageId(reply) ==
+ IPC::SyncMessage::GetMessageId(msg))
+ return &reply;
+ }
+ return nullptr;
+}
+
// This is used to create a filter matching a specified child id.
class TestFilterSpecifyingChild : public ResourceMessageFilter {
public:
@@ -244,7 +258,6 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
NULL,
NULL,
NULL,
- NULL,
base::Bind(&TestFilterSpecifyingChild::GetContexts,
base::Unretained(this))),
resource_context_(resource_context),
@@ -619,16 +632,6 @@ class TestUserData : public base::SupportsUserData::Data {
bool* was_deleted_;
};
-class TransfersAllNavigationsContentBrowserClient
- : public TestContentBrowserClient {
- public:
- bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context,
- const GURL& current_url,
- const GURL& new_url) override {
- return true;
- }
-};
-
enum GenericResourceThrottleFlags {
NONE = 0,
DEFER_STARTING_REQUEST = 1 << 0,
@@ -872,6 +875,10 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
request_context->set_network_delegate(&network_delegate_);
}
+ ~ResourceDispatcherHostTest() override {
+ filter_->OnChannelClosing();
+ }
+
// IPC::Sender implementation
bool Send(IPC::Message* msg) override {
accum_.AddMessage(*msg);
@@ -909,16 +916,12 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
web_contents_->GetRenderProcessHost()->GetID());
child_ids_.insert(web_contents_->GetRenderProcessHost()->GetID());
- base::FeatureList::ClearInstanceForTesting();
switch (GetParam()) {
case TestConfig::kDefault:
- base::FeatureList::InitializeInstance(std::string(), std::string());
break;
case TestConfig::kOptimizeIPCForSmallResourceEnabled: {
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- features::kOptimizeLoadingIPCForSmallResources.name, std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kOptimizeLoadingIPCForSmallResources);
ASSERT_TRUE(base::FeatureList::IsEnabled(
features::kOptimizeLoadingIPCForSmallResources));
break;
@@ -927,6 +930,7 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
}
void TearDown() override {
+ web_contents_filter_->OnChannelClosing();
web_contents_observer_.reset();
web_contents_.reset();
@@ -1090,7 +1094,8 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
common_params.url = url;
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, begin_params, url,
- url::Origin(url), true, false, false, -1));
+ url::Origin(url), true, false, false, -1,
+ false, false));
std::unique_ptr<NavigationURLLoader> test_loader =
NavigationURLLoader::Create(browser_context_.get(),
std::move(request_info), nullptr, nullptr,
@@ -1143,6 +1148,7 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
std::unique_ptr<base::RunLoop> wait_for_request_complete_loop_;
RenderViewHostTestEnabler render_view_host_test_enabler_;
bool auto_advance_;
+ base::test::ScopedFeatureList scoped_feature_list_;
};
void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
@@ -1564,6 +1570,60 @@ TEST_P(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
EXPECT_EQ(0, network_delegate()->error_count());
}
+TEST_P(ResourceDispatcherHostTest, SyncLoadSuccess) {
+ ResourceRequest request = CreateResourceRequest(
+ "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_1());
+ request.priority = net::MAXIMUM_PRIORITY;
+
+ // Successful sync load.
+ std::tuple<SyncLoadResult> result;
+ ResourceHostMsg_SyncLoad sync_load_msg(0, 1, request, &std::get<0>(result));
+ host_.OnMessageReceived(sync_load_msg, filter_.get());
+ base::RunLoop().RunUntilIdle();
+
+ const IPC::Message* reply = accum_.GetReply(sync_load_msg);
+ ASSERT_TRUE(reply);
+
+ ASSERT_TRUE(ResourceHostMsg_SyncLoad::ReadReplyParam(reply, &result));
+ EXPECT_EQ(net::OK, std::get<0>(result).error_code);
+}
+
+TEST_P(ResourceDispatcherHostTest, SyncLoadError) {
+ ResourceRequest request = CreateResourceRequest(
+ "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_error());
+ request.priority = net::MAXIMUM_PRIORITY;
+
+ // Failued sync load.
+ std::tuple<SyncLoadResult> result;
+ ResourceHostMsg_SyncLoad sync_load_msg(0, 1, request, &std::get<0>(result));
+ host_.OnMessageReceived(sync_load_msg, filter_.get());
+ base::RunLoop().RunUntilIdle();
+
+ const IPC::Message* reply = accum_.GetReply(sync_load_msg);
+ ASSERT_TRUE(reply);
+
+ ASSERT_TRUE(ResourceHostMsg_SyncLoad::ReadReplyParam(reply, &result));
+ EXPECT_EQ(net::ERR_INVALID_URL, std::get<0>(result).error_code);
+}
+
+TEST_P(ResourceDispatcherHostTest, SyncLoadCancel) {
+ ResourceRequest request = CreateResourceRequest(
+ "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_1());
+ request.priority = net::MAXIMUM_PRIORITY;
+
+ // Cancelled sync load.
+ SyncLoadResult result;
+ ResourceHostMsg_SyncLoad sync_load_msg(0, 1, request, &result);
+
+ host_.OnMessageReceived(sync_load_msg, filter_.get());
+ host_.CancelRequestsForProcess(filter_->child_id());
+ base::RunLoop().RunUntilIdle();
+
+ const IPC::Message* reply = accum_.GetReply(sync_load_msg);
+ ASSERT_TRUE(reply);
+ ASSERT_TRUE(reply->is_reply_error());
+}
+
// If the filter has disappeared then detachable resources should continue to
// load.
TEST_P(ResourceDispatcherHostTest, DeletedFilterDetached) {
@@ -1905,6 +1965,8 @@ TEST_P(ResourceDispatcherHostTest, TestProcessCancel) {
EXPECT_EQ(4, network_delegate()->completed_requests());
EXPECT_EQ(0, network_delegate()->canceled_requests());
EXPECT_EQ(0, network_delegate()->error_count());
+
+ test_filter->OnChannelClosing();
}
// Tests whether the correct requests get canceled when a RenderViewHost is
@@ -2155,6 +2217,7 @@ TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
EXPECT_TRUE(host_.blocked_loaders_map_.empty());
+ second_filter->OnChannelClosing();
}
// Tests that blocked requests don't leak when the ResourceDispatcherHost goes
@@ -2200,6 +2263,8 @@ TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ second_filter->OnChannelClosing();
}
// Test the private helper method "CalculateApproximateMemoryCost()".
@@ -2207,15 +2272,13 @@ TEST_P(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::URLRequestContext context;
std::unique_ptr<net::URLRequest> req(context.CreateRequest(
GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL));
- EXPECT_EQ(
- 4427,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
+ EXPECT_EQ(4425, ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
+ req.get()));
// Add 9 bytes of referrer.
req->SetReferrer("123456789");
- EXPECT_EQ(
- 4436,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
+ EXPECT_EQ(4434, ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
+ req.get()));
// Add 33 bytes of upload content.
std::string upload_content;
@@ -2228,9 +2291,8 @@ TEST_P(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
// Since the upload throttling is disabled, this has no effect on the cost.
- EXPECT_EQ(
- 4436,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
+ EXPECT_EQ(4434, ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
+ req.get()));
}
// Test that too much memory for outstanding requests for a particular
@@ -2306,6 +2368,8 @@ TEST_P(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
net::URLRequestTestJob::test_data_2());
CheckSuccessfulRequest(msgs[kMaxRequests + 3],
net::URLRequestTestJob::test_data_2());
+
+ second_filter->OnChannelClosing();
}
// Test that when too many requests are outstanding for a particular
@@ -2371,6 +2435,9 @@ TEST_P(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
CheckFailedRequest(msgs[kMaxRequestsPerProcess + 2],
net::URLRequestTestJob::test_data_2(),
net::ERR_INSUFFICIENT_RESOURCES);
+
+ second_filter->OnChannelClosing();
+ third_filter->OnChannelClosing();
}
// Tests that we sniff the mime type for a simple request.
@@ -2578,7 +2645,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, begin_params, download_url,
url::Origin(download_url), true, false, false,
- -1));
+ -1, false, false));
std::unique_ptr<NavigationURLLoader> loader = NavigationURLLoader::Create(
browser_context_.get(), std::move(request_info), nullptr, nullptr,
&delegate);
@@ -2687,7 +2754,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
GlobalRequestID global_request_id(web_contents_filter_->child_id(),
request_id);
- host_.MarkAsTransferredNavigation(global_request_id, nullptr);
+ host_.MarkAsTransferredNavigation(global_request_id, base::Closure());
// And now simulate a cancellation coming from the renderer.
ResourceHostMsg_CancelRequest msg(request_id);
@@ -2714,13 +2781,11 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
- // This test expects the cross site request to be leaked, so it can transfer
- // the request directly.
- CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
EXPECT_EQ(0, host_.pending_requests());
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
+ NavigationResourceThrottle::set_force_transfer_for_testing(true);
int render_view_id = 0;
int request_id = 1;
@@ -2731,11 +2796,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
HandleScheme("http");
- // Temporarily replace ContentBrowserClient with one that will trigger the
- // transfer navigation code paths.
- TransfersAllNavigationsContentBrowserClient new_client;
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
RESOURCE_TYPE_MAIN_FRAME);
@@ -2754,9 +2814,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
// MimeTypeResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- // Restore, now that we've set up a transfer.
- SetBrowserClientForTesting(old_client);
-
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
@@ -2780,6 +2837,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
CheckSuccessfulRequest(msgs[1], kResponseBody);
+
+ second_filter->OnChannelClosing();
}
// Test transferring two navigations with text/html, to ensure the resource
@@ -2789,10 +2848,8 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
- // This test expects the cross site request to be leaked, so it can transfer
- // the request directly.
- CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+ NavigationResourceThrottle::set_force_transfer_for_testing(true);
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
EXPECT_EQ(0, host_.pending_requests());
@@ -2808,11 +2865,6 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
HandleScheme("http");
- // Temporarily replace ContentBrowserClient with one that will trigger the
- // transfer navigation code paths.
- TransfersAllNavigationsContentBrowserClient new_client;
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
// Make the first request.
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
@@ -2829,8 +2881,7 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
// MimeTypeResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- // Restore, now that we've set up a transfer.
- SetBrowserClientForTesting(old_client);
+ NavigationResourceThrottle::set_force_transfer_for_testing(false);
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
@@ -2866,6 +2917,8 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
ASSERT_EQ(2U, msgs.size());
CheckSuccessfulRequest(msgs[0], kResponseBody);
+
+ second_filter->OnChannelClosing();
}
// Test transferred navigations with text/plain, which causes
@@ -2876,10 +2929,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
- // This test expects the cross site request to be leaked, so it can transfer
- // the request directly.
- CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+ NavigationResourceThrottle::set_force_transfer_for_testing(true);
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
EXPECT_EQ(0, host_.pending_requests());
@@ -2893,11 +2944,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
HandleScheme("http");
- // Temporarily replace ContentBrowserClient with one that will trigger the
- // transfer navigation code paths.
- TransfersAllNavigationsContentBrowserClient new_client;
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
RESOURCE_TYPE_MAIN_FRAME);
@@ -2919,9 +2965,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
base::RunLoop().RunUntilIdle();
- // Restore, now that we've set up a transfer.
- SetBrowserClientForTesting(old_client);
-
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
@@ -2945,6 +2988,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
CheckSuccessfulRequest(msgs[1], kResponseBody);
+
+ second_filter->OnChannelClosing();
}
TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
@@ -2952,10 +2997,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
- // This test expects the cross site request to be leaked, so it can transfer
- // the request directly.
- CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+ NavigationResourceThrottle::set_force_transfer_for_testing(true);
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
EXPECT_EQ(0, host_.pending_requests());
@@ -2971,11 +3014,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
HandleScheme("http");
- // Temporarily replace ContentBrowserClient with one that will trigger the
- // transfer navigation code paths.
- TransfersAllNavigationsContentBrowserClient new_client;
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
// Create a first filter that can be deleted before the second one starts.
{
scoped_refptr<ForwardingFilter> first_filter = MakeForwardingFilter();
@@ -3001,12 +3039,11 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ first_filter->OnChannelClosing();
}
// The first filter is now deleted, as if the child process died.
- // Restore.
- SetBrowserClientForTesting(old_client);
-
// Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
GlobalRequestID first_global_request_id(first_child_id, request_id);
@@ -3035,6 +3072,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
CheckSuccessfulRequest(msgs[1], kResponseBody);
+
+ second_filter->OnChannelClosing();
}
TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
@@ -3042,10 +3081,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
}
- // This test expects the cross site request to be leaked, so it can transfer
- // the request directly.
- CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+ NavigationResourceThrottle::set_force_transfer_for_testing(true);
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
EXPECT_EQ(0, host_.pending_requests());
@@ -3059,11 +3096,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
HandleScheme("http");
- // Temporarily replace ContentBrowserClient with one that will trigger the
- // transfer navigation code paths.
- TransfersAllNavigationsContentBrowserClient new_client;
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
RESOURCE_TYPE_MAIN_FRAME);
@@ -3092,9 +3124,6 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
base::RunLoop().RunUntilIdle();
- // Restore.
- SetBrowserClientForTesting(old_client);
-
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
@@ -3131,6 +3160,8 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
CheckSuccessfulRequest(msgs[1], kResponseBody);
+
+ second_filter->OnChannelClosing();
}
TEST_P(ResourceDispatcherHostTest, UnknownURLScheme) {
@@ -3755,6 +3786,72 @@ TEST_P(ResourceDispatcherHostTest, ThrottleMustProcessResponseBeforeRead) {
base::RunLoop().RunUntilIdle();
}
+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_P(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(0, 1, request, filter_.get(),
+ base::Bind(&StoreSyncLoadResult,
+ &called, &was_null, &result));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_FALSE(was_null);
+ EXPECT_EQ(net::OK, result.error_code);
+}
+
+TEST_P(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(0, 1, request, filter_.get(),
+ base::Bind(&StoreSyncLoadResult,
+ &called, &was_null, &result));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_FALSE(was_null);
+ EXPECT_EQ(net::ERR_INVALID_URL, result.error_code);
+}
+
+TEST_P(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(0, 1, request, filter_.get(),
+ base::Bind(&StoreSyncLoadResult,
+ &called, &was_null, &result));
+ host_.CancelRequestsForProcess(filter_->child_id());
+ base::RunLoop().RunUntilIdle();
+ 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 358dd65a90a..1c9287e3ad2 100644
--- a/chromium/content/browser/loader/resource_handler.cc
+++ b/chromium/content/browser/loader/resource_handler.cc
@@ -8,6 +8,8 @@
namespace content {
+ResourceHandler::~ResourceHandler() {}
+
ResourceHandler::ResourceHandler(net::URLRequest* request)
: controller_(NULL),
request_(request) {
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index 02ef6b87f12..a6cc6822c69 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -14,8 +14,9 @@
#include <string>
+#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner_helpers.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
@@ -40,7 +41,7 @@ struct ResourceResponse;
class CONTENT_EXPORT ResourceHandler
: public NON_EXPORTED_BASE(base::NonThreadSafe) {
public:
- virtual ~ResourceHandler() {}
+ virtual ~ResourceHandler();
// Sets the controller for this handler.
virtual void SetController(ResourceController* controller);
@@ -114,6 +115,8 @@ class CONTENT_EXPORT ResourceHandler
private:
ResourceController* controller_;
net::URLRequest* request_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceHandler);
};
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 6fda9a09bcb..f2f670a566d 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -6,18 +6,18 @@
#include <utility>
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/profiler/scoped_tracker.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
+#include "content/browser/loader/resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
@@ -25,6 +25,7 @@
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_manager.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"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
@@ -197,10 +198,11 @@ void ResourceLoader::CancelWithError(int error_code) {
}
void ResourceLoader::MarkAsTransferring(
- const scoped_refptr<ResourceResponse>& response) {
+ const base::Closure& on_transfer_complete_callback) {
CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
<< "Can only transfer for navigations";
is_transferring_ = true;
+ on_transfer_complete_callback_ = on_transfer_complete_callback;
int child_id = GetRequestInfo()->GetChildID();
AppCacheInterceptor::PrepareForCrossSiteTransfer(request(), child_id);
@@ -211,13 +213,14 @@ void ResourceLoader::MarkAsTransferring(
}
void ResourceLoader::CompleteTransfer() {
- // Although CrossSiteResourceHandler defers at OnResponseStarted
+ // Although NavigationResourceThrottle defers at WillProcessResponse
// (DEFERRED_READ), it may be seeing a replay of events via
- // MimeTypeResourceHandler, and so the request itself is actually deferred
- // at a later read stage.
+ // MimeTypeResourceHandler, and so the request itself is actually deferred at
+ // a later read stage.
DCHECK(DEFERRED_READ == deferred_stage_ ||
DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
DCHECK(is_transferring_);
+ DCHECK(!on_transfer_complete_callback_.is_null());
// In some cases, a process transfer doesn't really happen and the
// request is resumed in the original process. Real transfers to a new process
@@ -231,7 +234,7 @@ void ResourceLoader::CompleteTransfer() {
handler->MaybeCompleteCrossSiteTransferInOldProcess(child_id);
is_transferring_ = false;
- GetRequestInfo()->cross_site_handler()->ResumeResponse();
+ base::ResetAndReturn(&on_transfer_complete_callback_).Run();
}
ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
@@ -254,14 +257,21 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
ResourceRequestInfoImpl* info = GetRequestInfo();
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
- info->GetChildID(), redirect_info.new_url)) {
- DVLOG(1) << "Denied unauthorized request for "
- << redirect_info.new_url.possibly_invalid_spec();
+ // With PlzNavigate for frame navigations this check is done in the
+ // NavigationRequest::OnReceivedRedirect() function.
+ bool check_handled_elsewhere = IsBrowserSideNavigationEnabled() &&
+ IsResourceTypeFrame(info->GetResourceType());
- // Tell the renderer that this request was disallowed.
- Cancel();
- return;
+ if (!check_handled_elsewhere) {
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+ info->GetChildID(), redirect_info.new_url)) {
+ DVLOG(1) << "Denied unauthorized request for "
+ << redirect_info.new_url.possibly_invalid_spec();
+
+ // Tell the renderer that this request was disallowed.
+ Cancel();
+ return;
+ }
}
if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) {
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 8dcaf63fc45..6ebcd2de50b 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -7,10 +7,10 @@
#include <memory>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
-#include "content/browser/loader/resource_handler.h"
+#include "base/time/time.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/common/content_export.h"
@@ -23,6 +23,7 @@ class X509Certificate;
namespace content {
class ResourceDispatcherHostLoginDelegate;
+class ResourceHandler;
class ResourceLoaderDelegate;
class ResourceRequestInfoImpl;
@@ -43,7 +44,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void CancelRequest(bool from_renderer);
bool is_transferring() const { return is_transferring_; }
- void MarkAsTransferring(const scoped_refptr<ResourceResponse>& response);
+ void MarkAsTransferring(const base::Closure& on_transfer_complete_callback);
void CompleteTransfer();
net::URLRequest* request() { return request_.get(); }
@@ -129,6 +130,9 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// which point we'll receive a new ResourceHandler.
bool is_transferring_;
+ // Called when a navigation has finished transfer.
+ base::Closure on_transfer_complete_callback_;
+
// Instrumentation add to investigate http://crbug.com/503306.
// TODO(mmenke): Remove once bug is fixed.
int times_cancelled_before_request_start_;
diff --git a/chromium/content/browser/loader/resource_loader_delegate.h b/chromium/content/browser/loader/resource_loader_delegate.h
index 36702faf567..a6b2be979c0 100644
--- a/chromium/content/browser/loader/resource_loader_delegate.h
+++ b/chromium/content/browser/loader/resource_loader_delegate.h
@@ -7,6 +7,8 @@
#include "content/common/content_export.h"
+class GURL;
+
namespace net {
class AuthChallengeInfo;
class ClientCertStore;
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index b14afa1b422..2ee8ff5c7a7 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -6,8 +6,8 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/host_zoom_level_context.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/resource_context.h"
@@ -22,27 +22,34 @@ ResourceMessageFilter::ResourceMessageFilter(
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
- HostZoomLevelContext* host_zoom_level_context,
const GetContextsCallback& get_contexts_callback)
: BrowserMessageFilter(ResourceMsgStart),
+ BrowserAssociatedInterface<mojom::URLLoaderFactory>(this, this),
child_id_(child_id),
process_type_(process_type),
+ is_channel_closed_(false),
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context),
file_system_context_(file_system_context),
service_worker_context_(service_worker_context),
- host_zoom_level_context_(host_zoom_level_context),
get_contexts_callback_(get_contexts_callback),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
ResourceMessageFilter::~ResourceMessageFilter() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(is_channel_closed_);
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
}
void ResourceMessageFilter::OnChannelClosing() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// Unhook us from all pending network requests so they don't get sent to a
// deleted object.
ResourceDispatcherHostImpl::Get()->CancelRequestsForProcess(child_id_);
+
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ is_channel_closed_ = true;
}
bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
@@ -63,15 +70,28 @@ void ResourceMessageFilter::GetContexts(
request_context);
}
-const HostZoomMap* ResourceMessageFilter::GetHostZoomMap() const {
- if (host_zoom_level_context_.get())
- return host_zoom_level_context_->GetHostZoomMap();
- return NULL;
-}
-
base::WeakPtr<ResourceMessageFilter> ResourceMessageFilter::GetWeakPtr() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return weak_ptr_factory_.GetWeakPtr();
+ return is_channel_closed_ ? nullptr : weak_ptr_factory_.GetWeakPtr();
+}
+
+void ResourceMessageFilter::CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) {
+ URLLoaderFactoryImpl::CreateLoaderAndStart(std::move(request), routing_id,
+ request_id, url_request,
+ std::move(client_ptr_info), this);
+}
+
+void ResourceMessageFilter::SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ const SyncLoadCallback& callback) {
+ URLLoaderFactoryImpl::SyncLoad(routing_id, request_id, url_request, callback,
+ this);
}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 4037826d7b1..bcc07138851 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -11,8 +11,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
-#include "content/browser/host_zoom_level_context.h"
#include "content/common/content_export.h"
+#include "content/common/url_loader_factory.mojom.h"
+#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/resource_type.h"
@@ -37,7 +38,10 @@ class ServiceWorkerContextWrapper;
// delayed by costly UI processing that may be occuring on the main thread of
// the browser. It also means that any hangs in starting a network request
// will not interfere with browser UI.
-class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
+class CONTENT_EXPORT ResourceMessageFilter
+ : public BrowserMessageFilter,
+ public BrowserAssociatedInterface<mojom::URLLoaderFactory>,
+ public mojom::URLLoaderFactory {
public:
typedef base::Callback<void(ResourceType resource_type,
ResourceContext**,
@@ -54,7 +58,6 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
- HostZoomLevelContext* host_zoom_level_context,
const GetContextsCallback& get_contexts_callback);
// BrowserMessageFilter implementation.
@@ -85,15 +88,22 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
return service_worker_context_.get();
}
- // Returns a raw pointer to the HostZoomLevelContext's associated HostZoomMap,
- // or NULL if no context is present.
- const HostZoomMap* GetHostZoomMap() const;
-
int child_id() const { return child_id_; }
int process_type() const { return process_type_; }
base::WeakPtr<ResourceMessageFilter> GetWeakPtr();
+ void CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) override;
+ void SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& request,
+ const SyncLoadCallback& callback) override;
+
protected:
// Protected destructor so that we can be overriden in tests.
~ResourceMessageFilter() override;
@@ -106,12 +116,12 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
int child_id_;
int process_type_;
+ bool is_channel_closed_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
scoped_refptr<storage::FileSystemContext> file_system_context_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- scoped_refptr<HostZoomLevelContext> host_zoom_level_context_;
GetContextsCallback get_contexts_callback_;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index d9f14b9706a..fc7d9730281 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -160,8 +160,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
const std::string& original_headers,
const scoped_refptr<ResourceRequestBodyImpl> body,
bool initiated_in_secure_context)
- : cross_site_handler_(NULL),
- detachable_handler_(NULL),
+ : detachable_handler_(NULL),
process_type_(process_type),
child_id_(child_id),
route_id_(route_id),
@@ -233,6 +232,10 @@ int ResourceRequestInfoImpl::GetRouteID() const {
return route_id_;
}
+GlobalRequestID ResourceRequestInfoImpl::GetGlobalRequestID() const {
+ return GlobalRequestID(child_id_, request_id_);
+}
+
int ResourceRequestInfoImpl::GetOriginPID() const {
return origin_pid_;
}
@@ -325,10 +328,6 @@ int ResourceRequestInfoImpl::GetRequestID() const {
return request_id_;
}
-GlobalRequestID ResourceRequestInfoImpl::GetGlobalRequestID() const {
- return GlobalRequestID(child_id_, request_id_);
-}
-
GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(child_id_, route_id_);
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 356efa4cf8a..97cc7198960 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -7,12 +7,14 @@
#include <memory>
#include <string>
+#include <utility>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/resource_request_info.h"
@@ -21,7 +23,6 @@
#include "net/base/load_states.h"
namespace content {
-class CrossSiteResourceHandler;
class DetachableResourceHandler;
class ResourceContext;
class ResourceMessageFilter;
@@ -78,6 +79,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
ResourceContext* GetContext() const override;
int GetChildID() const override;
int GetRouteID() const override;
+ GlobalRequestID GetGlobalRequestID() const override;
int GetOriginPID() const override;
int GetRenderFrameID() const override;
int GetFrameTreeNodeId() const override;
@@ -101,7 +103,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
CONTENT_EXPORT int GetRequestID() const;
- CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
// PlzNavigate
@@ -125,14 +126,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int request_id,
base::WeakPtr<ResourceMessageFilter> filter);
- // CrossSiteResourceHandler for this request. May be null.
- CrossSiteResourceHandler* cross_site_handler() {
- return cross_site_handler_;
- }
- void set_cross_site_handler(CrossSiteResourceHandler* h) {
- cross_site_handler_ = h;
- }
-
// Whether this request is part of a navigation that should replace the
// current session history entry. This state is shuffled up and down the stack
// for request transfers.
@@ -205,13 +198,23 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
navigation_ui_data_ = std::move(navigation_ui_data);
}
+ // PlzNavigate: used in navigations to store the ServiceWorkerContext, since
+ // the ResourceMessageFilter will be null in this case. All other requests
+ // should access the ServiceWorkerContext through the ResourceMessageFilter.
+ void set_service_worker_context(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
+ service_worker_context_ = service_worker_context;
+ }
+ ServiceWorkerContextWrapper* service_worker_context() const {
+ return service_worker_context_.get();
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DeletedFilterDetached);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DeletedFilterDetachedRedirect);
// Non-owning, may be NULL.
- CrossSiteResourceHandler* cross_site_handler_;
DetachableResourceHandler* detachable_handler_;
int process_type_;
@@ -249,6 +252,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
scoped_refptr<ResourceRequestBodyImpl> body_;
bool initiated_in_secure_context_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl);
};
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index 2253b57d4a9..ad67fa91cd5 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -10,6 +10,7 @@
#include <utility>
#include <vector>
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
@@ -31,6 +32,13 @@ namespace content {
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.
+const base::Feature kPrioritySupportedRequestsDelayable{
+ "PrioritySupportedRequestsDelayable", base::FEATURE_DISABLED_BY_DEFAULT};
+
enum StartMode {
START_SYNC,
START_ASYNC
@@ -170,6 +178,7 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
scheduler_(scheduler),
priority_(priority),
fifo_ordering_(0),
+ host_port_pair_(net::HostPortPair::FromURL(request->url())),
weak_ptr_factory_(this) {
DCHECK(!request_->GetUserData(kUserDataKey));
request_->SetUserData(kUserDataKey, new UnownedPointer(this));
@@ -235,6 +244,7 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
void set_attributes(RequestAttributes attributes) {
attributes_ = attributes;
}
+ const net::HostPortPair& host_port_pair() const { return host_port_pair_; }
private:
class UnownedPointer : public base::SupportsUserData::Data {
@@ -268,6 +278,8 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
ResourceScheduler* scheduler_;
RequestPriorityParams priority_;
uint32_t fifo_ordering_;
+ // Cached to excessive recomputation in ShouldKeepSearching.
+ const net::HostPortPair host_port_pair_;
base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest>
weak_ptr_factory_;
@@ -304,12 +316,13 @@ void ResourceScheduler::RequestQueue::Insert(
// Each client represents a tab.
class ResourceScheduler::Client {
public:
- explicit Client(ResourceScheduler* scheduler)
+ explicit Client(bool priority_requests_delayable)
: is_loaded_(false),
has_html_body_(false),
using_spdy_proxy_(false),
in_flight_delayable_count_(0),
- total_layout_blocking_count_(0) {}
+ total_layout_blocking_count_(0),
+ priority_requests_delayable_(priority_requests_delayable) {}
~Client() {}
@@ -513,14 +526,20 @@ class ResourceScheduler::Client {
attributes |= kAttributeLayoutBlocking;
} else if (request->url_request()->priority() <
kDelayablePriorityThreshold) {
- // Resources below the delayable priority threshold that are being
- // requested from a server that does not support native prioritization are
- // considered delayable.
- url::SchemeHostPort scheme_host_port(request->url_request()->url());
- net::HttpServerProperties& http_server_properties =
- *request->url_request()->context()->http_server_properties();
- if (!http_server_properties.SupportsRequestPriority(scheme_host_port))
+ if (priority_requests_delayable_) {
+ // Resources below the delayable priority threshold that are considered
+ // delayable.
attributes |= kAttributeDelayable;
+ } else {
+ // Resources below the delayable priority threshold that are being
+ // requested from a server that does not support native prioritization
+ // are considered delayable.
+ url::SchemeHostPort scheme_host_port(request->url_request()->url());
+ net::HttpServerProperties& http_server_properties =
+ *request->url_request()->context()->http_server_properties();
+ if (!http_server_properties.SupportsRequestPriority(scheme_host_port))
+ attributes |= kAttributeDelayable;
+ }
}
return attributes;
@@ -531,9 +550,7 @@ class ResourceScheduler::Client {
size_t same_host_count = 0;
for (RequestSet::const_iterator it = in_flight_requests_.begin();
it != in_flight_requests_.end(); ++it) {
- net::HostPortPair host_port_pair =
- net::HostPortPair::FromURL((*it)->url_request()->url());
- if (active_request_host.Equals(host_port_pair)) {
+ if (active_request_host.Equals((*it)->host_port_pair())) {
same_host_count++;
if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient)
return true;
@@ -595,20 +612,23 @@ class ResourceScheduler::Client {
if (!url_request.url().SchemeIsHTTPOrHTTPS())
return START_REQUEST;
- if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme))
- return START_REQUEST;
+ const net::HostPortPair& host_port_pair = request->host_port_pair();
- net::HostPortPair host_port_pair =
- net::HostPortPair::FromURL(url_request.url());
- url::SchemeHostPort scheme_host_port(url_request.url());
- net::HttpServerProperties& http_server_properties =
- *url_request.context()->http_server_properties();
+ if (!priority_requests_delayable_) {
+ if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme))
+ return START_REQUEST;
- // 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 START_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 START_REQUEST;
+ }
// Non-delayable requests.
if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable))
@@ -698,9 +718,15 @@ class ResourceScheduler::Client {
size_t in_flight_delayable_count_;
// 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_;
};
-ResourceScheduler::ResourceScheduler() {}
+ResourceScheduler::ResourceScheduler()
+ : priority_requests_delayable_(
+ base::FeatureList::IsEnabled(kPrioritySupportedRequestsDelayable)) {}
ResourceScheduler::~ResourceScheduler() {
DCHECK(unowned_requests_.empty());
@@ -757,7 +783,7 @@ void ResourceScheduler::OnClientCreated(int child_id,
ClientId client_id = MakeClientId(child_id, route_id);
DCHECK(!base::ContainsKey(client_map_, client_id));
- Client* client = new Client(this);
+ Client* client = new Client(priority_requests_delayable_);
client_map_[client_id] = client;
}
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index 0b4218227b9..76b455c409f 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -20,7 +20,6 @@
#include "net/base/request_priority.h"
namespace net {
-class HostPortPair;
class URLRequest;
}
@@ -137,6 +136,10 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
size_t max_num_delayable_requests_;
RequestSet unowned_requests_;
+ // True if requests to servers that support priorities (e.g., H2/QUIC) can
+ // be delayed.
+ bool priority_requests_delayable_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceScheduler);
};
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 51b8a47b68e..cc40deabab4 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -8,18 +8,17 @@
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_vector.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "base/timer/mock_timer.h"
#include "base/timer/timer.h"
-#include "content/browser/browser_thread_impl.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_render_view_host_factory.h"
#include "content/test/test_web_contents.h"
#include "net/base/host_port_pair.h"
@@ -46,6 +45,9 @@ const int kRouteId2 = 67;
const int kBackgroundChildId = 35;
const int kBackgroundRouteId = 43;
+const char kPrioritySupportedRequestsDelayable[] =
+ "PrioritySupportedRequestsDelayable";
+
class TestRequest : public ResourceController {
public:
TestRequest(std::unique_ptr<net::URLRequest> url_request,
@@ -124,9 +126,7 @@ class FakeResourceContext : public ResourceContext {
class ResourceSchedulerTest : public testing::Test {
protected:
- ResourceSchedulerTest()
- : ui_thread_(BrowserThread::UI, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_) {
+ ResourceSchedulerTest() {
InitializeScheduler();
context_.set_http_server_properties(&http_server_properties_);
}
@@ -242,10 +242,7 @@ class ResourceSchedulerTest : public testing::Test {
return scheduler_.get();
}
- base::MessageLoopForIO message_loop_;
- BrowserThreadImpl ui_thread_;
- BrowserThreadImpl io_thread_;
- ResourceDispatcherHostImpl rdh_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<ResourceScheduler> scheduler_;
base::MockTimer* mock_timer_;
net::HttpServerPropertiesImpl http_server_properties_;
@@ -314,6 +311,11 @@ TEST_F(ResourceSchedulerTest, MediumDoesNotBlockCriticalComplete) {
}
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("",
+ kPrioritySupportedRequestsDelayable);
+ InitializeScheduler();
+
http_server_properties_.SetSupportsSpdy(
url::SchemeHostPort("https", "spdyhost", 443), true);
std::unique_ptr<TestRequest> high(
@@ -333,6 +335,32 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
EXPECT_TRUE(low2->started());
}
+TEST_F(ResourceSchedulerTest,
+ OneLowLoadsUntilBodyInsertedEvenSpdyWhenDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(kPrioritySupportedRequestsDelayable,
+ "");
+
+ InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low_spdy(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(low->started());
+ EXPECT_FALSE(low2->started());
+ EXPECT_FALSE(low_spdy->started());
+
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(low2->started());
+}
+
TEST_F(ResourceSchedulerTest, SpdyLowBlocksOtherLowUntilBodyInserted) {
http_server_properties_.SetSupportsSpdy(
url::SchemeHostPort("https", "spdyhost", 443), true);
@@ -631,6 +659,11 @@ TEST_F(ResourceSchedulerTest, NonHTTPSchedulesImmediately) {
}
TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("",
+ kPrioritySupportedRequestsDelayable);
+ InitializeScheduler();
+
std::unique_ptr<TestRequest> high(
NewRequest("http://host/high", net::HIGHEST));
std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
@@ -648,7 +681,35 @@ TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) {
EXPECT_TRUE(after->started());
}
+TEST_F(ResourceSchedulerTest, SpdyProxyDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(kPrioritySupportedRequestsDelayable,
+ "");
+ InitializeScheduler();
+
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::IDLE));
+ EXPECT_FALSE(request->started());
+
+ scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(request->started());
+
+ std::unique_ptr<TestRequest> after(
+ NewRequest("http://host/after", net::IDLE));
+ EXPECT_FALSE(after->started());
+}
+
TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("",
+ kPrioritySupportedRequestsDelayable);
+ InitializeScheduler();
+
scheduler()->OnWillInsertBody(kChildId, kRouteId);
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
@@ -682,6 +743,45 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
EXPECT_TRUE(low2->started());
}
+TEST_F(ResourceSchedulerTest, NewDelayableSpdyHostInDelayableRequests) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(kPrioritySupportedRequestsDelayable,
+ "");
+ InitializeScheduler();
+
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ const int kMaxNumDelayableRequestsPerClient = 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.
+ ScopedVector<TestRequest> lows;
+ for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) {
+ string url = "http://host" + base::IntToString(i) + "/low";
+ lows.push_back(NewRequest(url.c_str(), net::LOWEST));
+ }
+ std::unique_ptr<TestRequest> low1(NewRequest("http://host/low", net::LOWEST));
+ EXPECT_FALSE(low1->started());
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("http", "spdyhost1", 8080), true);
+ low1_spdy.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(low1->started());
+
+ low1.reset();
+ base::RunLoop().RunUntilIdle();
+ std::unique_ptr<TestRequest> low2_spdy(
+ NewRequest("http://spdyhost2:8080/low", net::IDLE));
+ // Reprioritize a request after we learn the server supports SPDY.
+ EXPECT_TRUE(low2_spdy->started());
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("http", "spdyhost2", 8080), true);
+ ChangeRequestPriority(low2_spdy.get(), net::LOWEST);
+ base::RunLoop().RunUntilIdle();
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ EXPECT_FALSE(low2->started());
+}
+
// Async revalidations which are not started when the tab is closed must be
// started at some point, or they will hang around forever and prevent other
// async revalidations to the same URL from being issued.
diff --git a/chromium/content/browser/loader/sync_resource_handler.cc b/chromium/content/browser/loader/sync_resource_handler.cc
index 47991f5fe24..b0475ce0db1 100644
--- a/chromium/content/browser/loader/sync_resource_handler.cc
+++ b/chromium/content/browser/loader/sync_resource_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/loader/sync_resource_handler.h"
+#include "base/callback_helpers.h"
#include "base/logging.h"
#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -20,25 +21,19 @@ namespace content {
SyncResourceHandler::SyncResourceHandler(
net::URLRequest* request,
- IPC::Message* result_message,
+ const SyncLoadResultCallback& result_handler,
ResourceDispatcherHostImpl* resource_dispatcher_host)
: ResourceHandler(request),
read_buffer_(new net::IOBuffer(kReadBufSize)),
- result_message_(result_message),
+ result_handler_(result_handler),
rdh_(resource_dispatcher_host),
total_transfer_size_(0) {
result_.final_url = request->url();
}
SyncResourceHandler::~SyncResourceHandler() {
- if (result_message_) {
- result_message_->set_reply_error();
- ResourceMessageFilter* filter = GetFilter();
- // If the filter doesn't exist at this point, the process has died and isn't
- // waiting for the result message anymore.
- if (filter)
- filter->Send(result_message_);
- }
+ if (result_handler_)
+ result_handler_.Run(nullptr);
}
bool SyncResourceHandler::OnRequestRedirected(
@@ -114,20 +109,13 @@ bool SyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
void SyncResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
bool* defer) {
- ResourceMessageFilter* filter = GetFilter();
- if (!filter)
- return;
-
result_.error_code = status.error();
int total_transfer_size = request()->GetTotalReceivedBytes();
result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
result_.encoded_body_length = request()->GetRawBodyBytes();
- ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
- filter->Send(result_message_);
- result_message_ = NULL;
- return;
+ base::ResetAndReturn(&result_handler_).Run(&result_);
}
void SyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
diff --git a/chromium/content/browser/loader/sync_resource_handler.h b/chromium/content/browser/loader/sync_resource_handler.h
index 00e2794002c..2ab87a79ca5 100644
--- a/chromium/content/browser/loader/sync_resource_handler.h
+++ b/chromium/content/browser/loader/sync_resource_handler.h
@@ -9,6 +9,7 @@
#include <string>
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_handler.h"
#include "content/public/common/resource_response.h"
@@ -22,16 +23,16 @@ class URLRequest;
}
namespace content {
-class ResourceContext;
-class ResourceDispatcherHostImpl;
-class ResourceMessageFilter;
// Used to complete a synchronous resource request in response to resource load
// events from the resource dispatcher host.
class SyncResourceHandler : public ResourceHandler {
public:
+ using SyncLoadResultCallback =
+ ResourceDispatcherHostImpl::SyncLoadResultCallback;
+
SyncResourceHandler(net::URLRequest* request,
- IPC::Message* result_message,
+ const SyncLoadResultCallback& sync_result_handler,
ResourceDispatcherHostImpl* resource_dispatcher_host);
~SyncResourceHandler() override;
@@ -54,7 +55,7 @@ class SyncResourceHandler : public ResourceHandler {
scoped_refptr<net::IOBuffer> read_buffer_;
SyncLoadResult result_;
- IPC::Message* result_message_;
+ SyncLoadResultCallback result_handler_;
ResourceDispatcherHostImpl* rdh_;
int64_t total_transfer_size_;
};
diff --git a/chromium/content/browser/loader/test_resource_handler.cc b/chromium/content/browser/loader/test_resource_handler.cc
new file mode 100644
index 00000000000..0ee72ae6744
--- /dev/null
+++ b/chromium/content/browser/loader/test_resource_handler.cc
@@ -0,0 +1,111 @@
+// 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/loader/test_resource_handler.h"
+
+#include "base/logging.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+TestResourceHandler::TestResourceHandler(net::URLRequestStatus* request_status,
+ std::string* body)
+ : ResourceHandler(nullptr), request_status_(request_status), body_(body) {
+ SetBufferSize(2048);
+}
+
+TestResourceHandler::TestResourceHandler()
+ : TestResourceHandler(nullptr, nullptr) {}
+
+TestResourceHandler::~TestResourceHandler() {}
+
+void TestResourceHandler::SetController(ResourceController* controller) {}
+
+bool TestResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
+ NOTREACHED() << "Redirects are not supported by the TestResourceHandler.";
+ return false;
+}
+
+bool TestResourceHandler::OnResponseStarted(ResourceResponse* response,
+ bool* defer) {
+ EXPECT_EQ(1, on_will_start_called_);
+ EXPECT_EQ(0, on_response_started_called_);
+ EXPECT_EQ(0, on_response_completed_called_);
+ ++on_response_started_called_;
+
+ if (!on_response_started_result_)
+ return false;
+ *defer = defer_on_response_started_;
+ defer_on_response_started_ = false;
+ return true;
+}
+
+bool TestResourceHandler::OnWillStart(const GURL& url, bool* defer) {
+ EXPECT_EQ(0, on_response_started_called_);
+ EXPECT_EQ(0, on_will_start_called_);
+ EXPECT_EQ(0, on_response_completed_called_);
+ ++on_will_start_called_;
+
+ if (!on_will_start_result_)
+ return false;
+
+ *defer = defer_on_will_start_;
+ return true;
+}
+
+bool TestResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
+ EXPECT_EQ(0, on_response_completed_called_);
+ ++on_will_read_called_;
+
+ *buf = buffer_;
+ *buf_size = buffer_size_;
+ memset(buffer_->data(), '\0', buffer_size_);
+ return on_will_read_result_;
+}
+
+bool TestResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
+ EXPECT_EQ(1, on_will_start_called_);
+ EXPECT_EQ(1, on_response_started_called_);
+ EXPECT_EQ(0, on_response_completed_called_);
+ ++on_read_completed_called_;
+
+ EXPECT_LE(static_cast<size_t>(bytes_read), buffer_size_);
+ if (body_)
+ body_->append(buffer_->data(), bytes_read);
+ if (!on_read_completed_result_)
+ return false;
+ *defer = defer_on_read_completed_;
+ defer_on_read_completed_ = false;
+ return true;
+}
+
+void TestResourceHandler::OnResponseCompleted(
+ const net::URLRequestStatus& status,
+ bool* defer) {
+ EXPECT_EQ(0, on_response_completed_called_);
+ ++on_response_completed_called_;
+
+ if (request_status_)
+ *request_status_ = status;
+ *defer = defer_on_response_completed_;
+ defer_on_response_completed_ = false;
+}
+
+void TestResourceHandler::OnDataDownloaded(int bytes_downloaded) {
+ NOTREACHED() << "Saving to file is not supported by the TestResourceHandler.";
+}
+
+void TestResourceHandler::SetBufferSize(int buffer_size) {
+ buffer_ = new net::IOBuffer(buffer_size);
+ buffer_size_ = buffer_size;
+ memset(buffer_->data(), '\0', buffer_size);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/test_resource_handler.h b/chromium/content/browser/loader/test_resource_handler.h
new file mode 100644
index 00000000000..134f9a6e42c
--- /dev/null
+++ b/chromium/content/browser/loader/test_resource_handler.h
@@ -0,0 +1,132 @@
+// 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_LOADER_TEST_RESOURCE_HANDLER_H_
+#define CONTENT_BROWSER_LOADER_TEST_RESOURCE_HANDLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/loader/resource_handler.h"
+#include "net/base/io_buffer.h"
+
+class GURL;
+
+namespace net {
+class URLRequest;
+class URLRequestStatus;
+}
+
+namespace content {
+
+class ResourceHandler;
+struct ResourceResponse;
+
+// A test version of a ResourceHandler. It returns a configurable buffer in
+// response to OnWillStart. It records what ResourceHandler methods are called,
+// and verifies that they are called in the correct order. It can optionally
+// defer or fail the request at any stage, and record the response body and
+// final status it sees. Redirects currently not supported.
+class TestResourceHandler : public ResourceHandler {
+ public:
+ // If non-null, |request_status| will be updated when the response is complete
+ // with the final status of the request received by the handler and |body|
+ // will be updated on each OnReadCompleted call.
+ TestResourceHandler(net::URLRequestStatus* request_status, std::string* body);
+ TestResourceHandler();
+ ~TestResourceHandler() override;
+
+ // ResourceHandler implementation:
+ void SetController(ResourceController* controller) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
+
+ // Sets the size of the read buffer returned by OnWillRead. Releases reference
+ // to previous read buffer. Default size is 2048 bytes.
+ void SetBufferSize(int buffer_size);
+
+ scoped_refptr<net::IOBuffer> buffer() const { return buffer_; }
+
+ // Sets the result returned by each method. All default to returning true.
+ void set_on_will_start_result(bool on_will_start_result) {
+ on_will_start_result_ = on_will_start_result;
+ }
+ void set_on_response_started_result(bool on_response_started_result) {
+ on_response_started_result_ = on_response_started_result;
+ }
+ void set_on_will_read_result(bool on_will_read_result) {
+ on_will_read_result_ = on_will_read_result;
+ }
+ void set_on_read_completed_result(bool on_read_completed_result) {
+ on_read_completed_result_ = on_read_completed_result;
+ }
+
+ // Cause |defer| to be set to true when the specified method is invoked. The
+ // test itself is responsible for resuming the request after deferral.
+
+ void set_defer_on_will_start(bool defer_on_will_start) {
+ defer_on_will_start_ = defer_on_will_start;
+ }
+ void set_defer_on_response_started(bool defer_on_response_started) {
+ defer_on_response_started_ = defer_on_response_started;
+ }
+ // Only the next OnReadCompleted call will set |defer| to true.
+ void set_defer_on_read_completed(bool defer_on_read_completed) {
+ defer_on_read_completed_ = defer_on_read_completed;
+ }
+ void set_defer_on_response_completed(bool defer_on_response_completed) {
+ defer_on_response_completed_ = defer_on_response_completed;
+ }
+
+ // Return the number of times the corresponding method was invoked.
+
+ int on_will_start_called() const { return on_will_start_called_; }
+ // Redirection currently not supported.
+ int on_request_redirected_called() const { return 0; }
+ int on_response_started_called() const { return on_response_started_called_; }
+ int on_will_read_called() const { return on_will_read_called_; }
+ int on_read_completed_called() const { return on_read_completed_called_; }
+ int on_response_completed_called() const {
+ return on_response_completed_called_;
+ }
+
+ private:
+ net::URLRequestStatus* request_status_;
+ std::string* body_;
+ scoped_refptr<net::IOBuffer> buffer_;
+ size_t buffer_size_;
+
+ bool on_will_start_result_ = true;
+ bool on_response_started_result_ = true;
+ bool on_will_read_result_ = true;
+ bool on_read_completed_result_ = true;
+
+ bool defer_on_will_start_ = false;
+ bool defer_on_response_started_ = false;
+ bool defer_on_read_completed_ = false;
+ bool defer_on_response_completed_ = false;
+
+ int on_will_start_called_ = 0;
+ int on_response_started_called_ = 0;
+ int on_will_read_called_ = 0;
+ int on_read_completed_called_ = 0;
+ int on_response_completed_called_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResourceHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_TEST_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/test_url_loader_client.cc b/chromium/content/browser/loader/test_url_loader_client.cc
index 035a050d28a..caa858312f4 100644
--- a/chromium/content/browser/loader/test_url_loader_client.cc
+++ b/chromium/content/browser/loader/test_url_loader_client.cc
@@ -4,7 +4,9 @@
#include "content/browser/loader/test_url_loader_client.h"
+#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -15,8 +17,31 @@ void TestURLLoaderClient::OnReceiveResponse(
const ResourceResponseHead& response_head) {
has_received_response_ = true;
response_head_ = response_head;
- if (quit_closure_for_on_received_response_)
- quit_closure_for_on_received_response_.Run();
+ if (quit_closure_for_on_receive_response_)
+ quit_closure_for_on_receive_response_.Run();
+}
+
+void TestURLLoaderClient::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) {
+ EXPECT_FALSE(response_body_.is_valid());
+ EXPECT_FALSE(has_received_response_);
+ // Use ClearHasReceivedRedirect to accept more redirects.
+ EXPECT_FALSE(has_received_redirect_);
+ has_received_redirect_ = true;
+ redirect_info_ = redirect_info;
+ response_head_ = response_head;
+ if (quit_closure_for_on_receive_redirect_)
+ quit_closure_for_on_receive_redirect_.Run();
+}
+
+void TestURLLoaderClient::OnDataDownloaded(int64_t data_length,
+ int64_t encoded_data_length) {
+ has_data_downloaded_ = true;
+ download_data_length_ += data_length;
+ encoded_download_data_length_ += encoded_data_length;
+ if (quit_closure_for_on_data_downloaded_)
+ quit_closure_for_on_data_downloaded_.Run();
}
void TestURLLoaderClient::OnStartLoadingResponseBody(
@@ -34,8 +59,16 @@ void TestURLLoaderClient::OnComplete(
quit_closure_for_on_complete_.Run();
}
-mojom::URLLoaderClientPtr TestURLLoaderClient::CreateInterfacePtrAndBind() {
- return binding_.CreateInterfacePtrAndBind();
+void TestURLLoaderClient::ClearHasReceivedRedirect() {
+ has_received_redirect_ = false;
+}
+
+mojom::URLLoaderClientAssociatedPtrInfo
+TestURLLoaderClient::CreateRemoteAssociatedPtrInfo(
+ mojo::AssociatedGroup* associated_group) {
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info;
+ binding_.Bind(&client_ptr_info, associated_group);
+ return client_ptr_info;
}
void TestURLLoaderClient::Unbind() {
@@ -45,9 +78,23 @@ void TestURLLoaderClient::Unbind() {
void TestURLLoaderClient::RunUntilResponseReceived() {
base::RunLoop run_loop;
- quit_closure_for_on_received_response_ = run_loop.QuitClosure();
+ quit_closure_for_on_receive_response_ = run_loop.QuitClosure();
+ run_loop.Run();
+ quit_closure_for_on_receive_response_.Reset();
+}
+
+void TestURLLoaderClient::RunUntilRedirectReceived() {
+ base::RunLoop run_loop;
+ quit_closure_for_on_receive_redirect_ = run_loop.QuitClosure();
+ run_loop.Run();
+ quit_closure_for_on_receive_redirect_.Reset();
+}
+
+void TestURLLoaderClient::RunUntilDataDownloaded() {
+ base::RunLoop run_loop;
+ quit_closure_for_on_data_downloaded_ = run_loop.QuitClosure();
run_loop.Run();
- quit_closure_for_on_received_response_.Reset();
+ quit_closure_for_on_data_downloaded_.Reset();
}
void TestURLLoaderClient::RunUntilResponseBodyArrived() {
diff --git a/chromium/content/browser/loader/test_url_loader_client.h b/chromium/content/browser/loader/test_url_loader_client.h
index 78cb46f3f27..a12709bcca6 100644
--- a/chromium/content/browser/loader/test_url_loader_client.h
+++ b/chromium/content/browser/loader/test_url_loader_client.h
@@ -5,13 +5,17 @@
#ifndef CONTENT_BROWSER_LOADER_TEST_URL_LOADER_CLIENT_H_
#define CONTENT_BROWSER_LOADER_TEST_URL_LOADER_CLIENT_H_
+#include <stdint.h>
+
#include "base/callback.h"
#include "base/macros.h"
#include "content/common/resource_request_completion_status.h"
#include "content/common/url_loader.mojom.h"
+#include "content/common/url_loader_factory.mojom.h"
#include "content/public/common/resource_response.h"
#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "net/url_request/redirect_info.h"
namespace content {
@@ -25,35 +29,61 @@ class TestURLLoaderClient final : public mojom::URLLoaderClient {
~TestURLLoaderClient() override;
void OnReceiveResponse(const ResourceResponseHead& response_head) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) override;
+ void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const ResourceRequestCompletionStatus& status) override;
bool has_received_response() const { return has_received_response_; }
+ bool has_received_redirect() const { return has_received_redirect_; }
+ bool has_data_downloaded() const { return has_data_downloaded_; }
bool has_received_completion() const { return has_received_completion_; }
const ResourceResponseHead& response_head() const { return response_head_; }
+ const net::RedirectInfo& redirect_info() const { return redirect_info_; }
mojo::DataPipeConsumerHandle response_body() { return response_body_.get(); }
const ResourceRequestCompletionStatus& completion_status() const {
return completion_status_;
}
+ int64_t download_data_length() const { return download_data_length_; }
+ int64_t encoded_download_data_length() const {
+ return encoded_download_data_length_;
+ }
+
+ void ClearHasReceivedRedirect();
+ // Creates an AssociatedPtrInfo, binds it to |*this| and returns it. The
+ // returned PtrInfo is marked as remote, i.e., expected to be passed to the
+ // remote endpoint.
+ mojom::URLLoaderClientAssociatedPtrInfo CreateRemoteAssociatedPtrInfo(
+ mojo::AssociatedGroup* associated_group);
- mojom::URLLoaderClientPtr CreateInterfacePtrAndBind();
void Unbind();
void RunUntilResponseReceived();
+ void RunUntilRedirectReceived();
+ void RunUntilDataDownloaded();
void RunUntilResponseBodyArrived();
void RunUntilComplete();
private:
- mojo::Binding<mojom::URLLoaderClient> binding_;
+ mojo::AssociatedBinding<mojom::URLLoaderClient> binding_;
ResourceResponseHead response_head_;
+ net::RedirectInfo redirect_info_;
mojo::ScopedDataPipeConsumerHandle response_body_;
ResourceRequestCompletionStatus completion_status_;
bool has_received_response_ = false;
+ bool has_received_redirect_ = false;
+ bool has_data_downloaded_ = false;
bool has_received_completion_ = false;
- base::Closure quit_closure_for_on_received_response_;
+ base::Closure quit_closure_for_on_receive_response_;
+ base::Closure quit_closure_for_on_receive_redirect_;
+ base::Closure quit_closure_for_on_data_downloaded_;
base::Closure quit_closure_for_on_start_loading_response_body_;
base::Closure quit_closure_for_on_complete_;
+ mojom::URLLoaderFactoryPtr url_loader_factory_;
+ int64_t download_data_length_ = 0;
+ int64_t encoded_download_data_length_ = 0;
DISALLOW_COPY_AND_ASSIGN(TestURLLoaderClient);
};
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index f3d79c6fd5a..389a8e9b394 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
#include "content/common/resource_request_body_impl.h"
#include "net/base/elements_upload_data_stream.h"
@@ -24,6 +25,10 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/upload_blob_element_reader.h"
+namespace base {
+class TaskRunner;
+}
+
namespace disk_cache {
class Entry;
}
diff --git a/chromium/content/browser/loader/url_loader_factory_impl.cc b/chromium/content/browser/loader/url_loader_factory_impl.cc
index 7b11666452e..c510c147f2b 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl.cc
@@ -13,6 +13,26 @@
namespace content {
+namespace {
+
+void DispatchSyncLoadResult(
+ const 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;
+ callback.Run(failure);
+ return;
+ }
+
+ callback.Run(*result);
+}
+
+} // namespace
+
URLLoaderFactoryImpl::URLLoaderFactoryImpl(
scoped_refptr<ResourceMessageFilter> resource_message_filter)
: resource_message_filter_(std::move(resource_message_filter)) {
@@ -25,17 +45,53 @@ URLLoaderFactoryImpl::~URLLoaderFactoryImpl() {
}
void URLLoaderFactoryImpl::CreateLoaderAndStart(
- mojom::URLLoaderRequest request,
+ mojom::URLLoaderAssociatedRequest request,
int32_t routing_id,
int32_t request_id,
const ResourceRequest& url_request,
- mojom::URLLoaderClientPtr client) {
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) {
+ CreateLoaderAndStart(std::move(request), routing_id, request_id, url_request,
+ std::move(client_ptr_info),
+ resource_message_filter_.get());
+}
+
+void URLLoaderFactoryImpl::SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ const SyncLoadCallback& callback) {
+ SyncLoad(routing_id, request_id, url_request, callback,
+ resource_message_filter_.get());
+}
+
+// static
+void URLLoaderFactoryImpl::CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info,
+ ResourceMessageFilter* filter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ mojom::URLLoaderClientAssociatedPtr client;
+ client.Bind(std::move(client_ptr_info));
+
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
rdh->OnRequestResourceWithMojo(routing_id, request_id, url_request,
- std::move(request), std::move(client),
- resource_message_filter_.get());
+ std::move(request), std::move(client), filter);
+}
+
+// static
+void URLLoaderFactoryImpl::SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ const SyncLoadCallback& callback,
+ ResourceMessageFilter* filter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ rdh->OnSyncLoadWithMojo(routing_id, request_id, url_request, filter,
+ base::Bind(&DispatchSyncLoadResult, callback));
}
void URLLoaderFactoryImpl::Create(
diff --git a/chromium/content/browser/loader/url_loader_factory_impl.h b/chromium/content/browser/loader/url_loader_factory_impl.h
index a54c44bf6c6..e989c3d872b 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl.h
+++ b/chromium/content/browser/loader/url_loader_factory_impl.h
@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/url_loader_factory.mojom.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
namespace content {
@@ -21,11 +20,29 @@ class URLLoaderFactoryImpl final : public mojom::URLLoaderFactory {
public:
~URLLoaderFactoryImpl() override;
- void CreateLoaderAndStart(mojom::URLLoaderRequest request,
- int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& url_request,
- mojom::URLLoaderClientPtr client) override;
+ void CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) override;
+ void SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& request,
+ const SyncLoadCallback& callback) override;
+
+ static void CreateLoaderAndStart(
+ mojom::URLLoaderAssociatedRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info,
+ ResourceMessageFilter* filter);
+ static void SyncLoad(int32_t routing_id,
+ int32_t request_id,
+ const ResourceRequest& request,
+ const SyncLoadCallback& callback,
+ ResourceMessageFilter* filter);
// Creates a URLLoaderFactoryImpl instance. The instance is held by the
// StrongBinding in it, so this function doesn't return the instance.
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 84d082b6292..97f81a3f83b 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/url_loader_factory_impl.h"
+#include <stdint.h>
+
#include <memory>
#include <string>
#include <utility>
@@ -46,6 +48,7 @@
#include "net/http/http_util.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/test/url_request/url_request_mock_http_job.h"
+#include "net/test/url_request/url_request_slow_download_job.h"
#include "net/url_request/url_request_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -90,7 +93,6 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
nullptr,
nullptr,
nullptr,
- nullptr,
base::Bind(&URLLoaderFactoryImplTest::GetContexts,
base::Unretained(this)))) {
MojoAsyncResourceHandler::SetAllocationSizeForTesting(GetParam());
@@ -108,6 +110,7 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
rdh_.SetDelegate(nullptr);
net::URLRequestFilter::GetInstance()->ClearHandlers();
+ resource_message_filter_->OnChannelClosing();
rdh_.CancelRequestsForProcess(resource_message_filter_->child_id());
base::RunLoop().RunUntilIdle();
MojoAsyncResourceHandler::SetAllocationSizeForTesting(
@@ -136,7 +139,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::URLLoaderPtr loader;
+ mojom::URLLoaderAssociatedPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root,
@@ -147,9 +150,10 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
request.url = net::URLRequestMockHTTPJob::GetMockUrl("hello.html");
request.method = "GET";
request.is_main_frame = true;
- factory_->CreateLoaderAndStart(mojo::GetProxy(&loader), kRoutingId,
- kRequestId, request,
- client.CreateInterfacePtrAndBind());
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), kRoutingId,
+ kRequestId, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
ASSERT_FALSE(client.has_received_response());
ASSERT_FALSE(client.response_body().is_valid());
@@ -168,7 +172,6 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
EXPECT_EQ(kRequestId, request_info->GetRequestID());
ASSERT_FALSE(client.has_received_completion());
- ASSERT_FALSE(client.has_received_completion());
client.RunUntilResponseBodyArrived();
ASSERT_TRUE(client.response_body().is_valid());
@@ -204,15 +207,16 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
TEST_P(URLLoaderFactoryImplTest, GetFailedResponse) {
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderPtr loader;
+ mojom::URLLoaderAssociatedPtr loader;
ResourceRequest request;
TestURLLoaderClient client;
net::URLRequestFailedJob::AddUrlHandler();
request.url = net::URLRequestFailedJob::GetMockHttpUrlWithFailurePhase(
net::URLRequestFailedJob::START, net::ERR_TIMED_OUT);
request.method = "GET";
- factory_->CreateLoaderAndStart(mojo::GetProxy(&loader), 2, 1, request,
- client.CreateInterfacePtrAndBind());
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), 2, 1, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
client.RunUntilComplete();
ASSERT_FALSE(client.has_received_response());
@@ -223,14 +227,15 @@ TEST_P(URLLoaderFactoryImplTest, GetFailedResponse) {
// This test tests a case where resource loading is cancelled before started.
TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
- mojom::URLLoaderPtr loader;
+ mojom::URLLoaderAssociatedPtr loader;
ResourceRequest request;
TestURLLoaderClient client;
request.url = GURL();
request.method = "GET";
ASSERT_FALSE(request.url.is_valid());
- factory_->CreateLoaderAndStart(mojo::GetProxy(&loader), 2, 1, request,
- client.CreateInterfacePtrAndBind());
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), 2, 1, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
client.RunUntilComplete();
ASSERT_FALSE(client.has_received_response());
@@ -241,15 +246,16 @@ TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
// This test tests a case where resource loading is cancelled before started.
TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
- mojom::URLLoaderPtr loader;
+ mojom::URLLoaderAssociatedPtr loader;
RejectingResourceDispatcherHostDelegate rdh_delegate;
rdh_.SetDelegate(&rdh_delegate);
ResourceRequest request;
TestURLLoaderClient client;
request.url = GURL("http://localhost/");
request.method = "GET";
- factory_->CreateLoaderAndStart(mojo::GetProxy(&loader), 2, 1, request,
- client.CreateInterfacePtrAndBind());
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), 2, 1, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
client.RunUntilComplete();
rdh_.SetDelegate(nullptr);
@@ -260,6 +266,160 @@ TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
+TEST_P(URLLoaderFactoryImplTest, DownloadToFile) {
+ constexpr int32_t kRoutingId = 1;
+ constexpr int32_t kRequestId = 2;
+
+ mojom::URLLoaderAssociatedPtr loader;
+ base::FilePath root;
+ PathService::Get(DIR_TEST_DATA, &root);
+ net::URLRequestMockHTTPJob::AddUrlHandlers(root,
+ BrowserThread::GetBlockingPool());
+
+ ResourceRequest request;
+ TestURLLoaderClient client;
+ request.url = net::URLRequestMockHTTPJob::GetMockUrl("hello.html");
+ request.method = "GET";
+ request.resource_type = RESOURCE_TYPE_XHR;
+ request.download_to_file = true;
+ request.request_initiator = url::Origin();
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), kRoutingId,
+ kRequestId, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
+ ASSERT_FALSE(client.has_received_response());
+ ASSERT_FALSE(client.has_data_downloaded());
+ ASSERT_FALSE(client.has_received_completion());
+
+ client.RunUntilResponseReceived();
+
+ net::URLRequest* url_request =
+ rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
+ ASSERT_TRUE(url_request);
+ ResourceRequestInfoImpl* request_info =
+ ResourceRequestInfoImpl::ForRequest(url_request);
+ ASSERT_TRUE(request_info);
+ EXPECT_EQ(kChildId, request_info->GetChildID());
+ EXPECT_EQ(kRoutingId, request_info->GetRouteID());
+ EXPECT_EQ(kRequestId, request_info->GetRequestID());
+
+ ASSERT_FALSE(client.has_received_completion());
+
+ client.RunUntilComplete();
+ ASSERT_TRUE(client.has_data_downloaded());
+ ASSERT_TRUE(client.has_received_completion());
+
+ EXPECT_EQ(200, client.response_head().headers->response_code());
+ std::string content_type;
+ client.response_head().headers->GetNormalizedHeader("content-type",
+ &content_type);
+ EXPECT_EQ("text/html", content_type);
+ EXPECT_EQ(0, client.completion_status().error_code);
+
+ std::string contents;
+ base::ReadFileToString(client.response_head().download_file_path, &contents);
+
+ EXPECT_EQ(static_cast<int64_t>(contents.size()),
+ client.download_data_length());
+ EXPECT_EQ(static_cast<int64_t>(contents.size()),
+ client.encoded_download_data_length());
+
+ std::string expected;
+ base::ReadFileToString(
+ root.Append(base::FilePath(FILE_PATH_LITERAL("hello.html"))), &expected);
+ EXPECT_EQ(expected, contents);
+}
+
+TEST_P(URLLoaderFactoryImplTest, DownloadToFileFailure) {
+ constexpr int32_t kRoutingId = 1;
+ constexpr int32_t kRequestId = 2;
+
+ mojom::URLLoaderAssociatedPtr loader;
+ base::FilePath root;
+ PathService::Get(DIR_TEST_DATA, &root);
+ net::URLRequestSlowDownloadJob::AddUrlHandler();
+
+ ResourceRequest request;
+ TestURLLoaderClient client;
+ request.url = GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl);
+ request.method = "GET";
+ request.resource_type = RESOURCE_TYPE_XHR;
+ request.download_to_file = true;
+ request.request_initiator = url::Origin();
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), kRoutingId,
+ kRequestId, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
+ ASSERT_FALSE(client.has_received_response());
+ ASSERT_FALSE(client.has_data_downloaded());
+ ASSERT_FALSE(client.has_received_completion());
+
+ client.RunUntilResponseReceived();
+
+ net::URLRequest* url_request =
+ rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
+ ASSERT_TRUE(url_request);
+ ResourceRequestInfoImpl* request_info =
+ ResourceRequestInfoImpl::ForRequest(url_request);
+ ASSERT_TRUE(request_info);
+ EXPECT_EQ(kChildId, request_info->GetChildID());
+ EXPECT_EQ(kRoutingId, request_info->GetRouteID());
+ EXPECT_EQ(kRequestId, request_info->GetRequestID());
+
+ ASSERT_FALSE(client.has_received_completion());
+
+ client.RunUntilDataDownloaded();
+ ASSERT_TRUE(client.has_data_downloaded());
+ ASSERT_FALSE(client.has_received_completion());
+ EXPECT_LT(0, client.download_data_length());
+ EXPECT_GE(
+ static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
+ client.download_data_length());
+ EXPECT_LT(0, client.encoded_download_data_length());
+ EXPECT_GE(
+ static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
+ client.encoded_download_data_length());
+
+ url_request->Cancel();
+ client.RunUntilComplete();
+
+ ASSERT_TRUE(client.has_received_completion());
+
+ EXPECT_EQ(200, client.response_head().headers->response_code());
+ EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+// Removing the loader in the remote side will cancel the request.
+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;
+ base::FilePath root;
+ PathService::Get(DIR_TEST_DATA, &root);
+ net::URLRequestFailedJob::AddUrlHandler();
+ ResourceRequest request;
+ TestURLLoaderClient client;
+ // Assume the file contents is small enough to be stored in the data pipe.
+ request.url = net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING);
+ request.method = "GET";
+ request.is_main_frame = true;
+ factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&loader, factory_.associated_group()), kRoutingId,
+ kRequestId, request,
+ client.CreateRemoteAssociatedPtrInfo(factory_.associated_group()));
+
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId)));
+ ASSERT_FALSE(client.has_received_response());
+ ASSERT_FALSE(client.response_body().is_valid());
+ ASSERT_FALSE(client.has_received_completion());
+
+ loader = nullptr;
+ base::RunLoop().RunUntilIdle();
+ ASSERT_FALSE(rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId)));
+}
+
INSTANTIATE_TEST_CASE_P(URLLoaderFactoryImplTest,
URLLoaderFactoryImplTest,
::testing::Values(128, 32 * 1024));
diff --git a/chromium/content/browser/manifest/manifest_browsertest.cc b/chromium/content/browser/manifest/manifest_browsertest.cc
index 7a9d1079103..55d45d664c9 100644
--- a/chromium/content/browser/manifest/manifest_browsertest.cc
+++ b/chromium/content/browser/manifest/manifest_browsertest.cc
@@ -35,11 +35,11 @@ class MockWebContentsDelegate : public WebContentsDelegate {
test_(test) {
}
- bool AddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override;
+ bool DidAddMessageToConsole(WebContents* source,
+ int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override;
private:
WebContents* web_contents_;
@@ -113,9 +113,9 @@ class ManifestBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(ManifestBrowserTest);
};
-// The implementation of AddMessageToConsole isn't inlined because it needs
+// The implementation of DidAddMessageToConsole isn't inlined because it needs
// to know about |test_|.
-bool MockWebContentsDelegate::AddMessageToConsole(
+bool MockWebContentsDelegate::DidAddMessageToConsole(
WebContents* source,
int32_t level,
const base::string16& message,
diff --git a/chromium/content/browser/manifest/manifest_manager_host.cc b/chromium/content/browser/manifest/manifest_manager_host.cc
index 699576cc5df..27e68f6003d 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.cc
+++ b/chromium/content/browser/manifest/manifest_manager_host.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
#include "content/common/manifest_manager_messages.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -32,16 +32,13 @@ ManifestManagerHost::ManifestManagerHost(WebContents* web_contents)
: WebContentsObserver(web_contents) {
}
-ManifestManagerHost::~ManifestManagerHost() {
- base::STLDeleteValues(&pending_get_callbacks_);
-}
+ManifestManagerHost::~ManifestManagerHost() {}
ManifestManagerHost::GetCallbackMap*
ManifestManagerHost::GetCallbackMapForFrame(
RenderFrameHost* render_frame_host) {
- FrameGetCallbackMap::iterator it =
- pending_get_callbacks_.find(render_frame_host);
- return it != pending_get_callbacks_.end() ? it->second : nullptr;
+ auto it = pending_get_callbacks_.find(render_frame_host);
+ return it != pending_get_callbacks_.end() ? it->second.get() : nullptr;
}
void ManifestManagerHost::RenderFrameDeleted(
@@ -58,7 +55,6 @@ void ManifestManagerHost::RenderFrameDeleted(
it.GetCurrentValue()->Run(GURL(), Manifest());
}
- delete callbacks;
pending_get_callbacks_.erase(render_frame_host);
}
@@ -67,7 +63,7 @@ void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host,
GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
if (!callbacks) {
callbacks = new GetCallbackMap();
- pending_get_callbacks_[render_frame_host] = callbacks;
+ pending_get_callbacks_[render_frame_host] = base::WrapUnique(callbacks);
}
int request_id = callbacks->Add(new GetManifestCallback(callback));
@@ -151,10 +147,8 @@ void ManifestManagerHost::OnRequestManifestResponse(
callback->Run(manifest_url, manifest);
callbacks->Remove(request_id);
- if (callbacks->IsEmpty()) {
- delete callbacks;
+ if (callbacks->IsEmpty())
pending_get_callbacks_.erase(render_frame_host);
- }
}
} // namespace content
diff --git a/chromium/content/browser/manifest/manifest_manager_host.h b/chromium/content/browser/manifest/manifest_manager_host.h
index ce593eccd51..8edc88be24b 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.h
+++ b/chromium/content/browser/manifest/manifest_manager_host.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_MANIFEST_MANIFEST_MANAGER_HOST_H_
#define CONTENT_BROWSER_MANIFEST_MANIFEST_MANAGER_HOST_H_
+#include <memory>
+
#include "base/callback_forward.h"
#include "base/id_map.h"
#include "base/macros.h"
@@ -38,7 +40,6 @@ class ManifestManagerHost : public WebContentsObserver {
private:
using GetCallbackMap = IDMap<GetManifestCallback, IDMapOwnPointer>;
- using FrameGetCallbackMap = base::hash_map<RenderFrameHost*, GetCallbackMap*>;
void OnRequestManifestResponse(
RenderFrameHost*, int request_id, const GURL&, const Manifest&);
@@ -46,7 +47,8 @@ class ManifestManagerHost : public WebContentsObserver {
// Returns the CallbackMap associated with the given RenderFrameHost, or null.
GetCallbackMap* GetCallbackMapForFrame(RenderFrameHost*);
- FrameGetCallbackMap pending_get_callbacks_;
+ base::hash_map<RenderFrameHost*, std::unique_ptr<GetCallbackMap>>
+ pending_get_callbacks_;
DISALLOW_COPY_AND_ASSIGN(ManifestManagerHost);
};
diff --git a/chromium/content/browser/media/OWNERS b/chromium/content/browser/media/OWNERS
index 5d85067ee22..a4c232a80e2 100644
--- a/chromium/content/browser/media/OWNERS
+++ b/chromium/content/browser/media/OWNERS
@@ -1,5 +1,6 @@
file://media/OWNERS
+per-file media_devices_*=guidou@chromium.org
per-file midi_*=toyoshim@chromium.org
# For changes related to the tab media indicators.
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 086b22a3c0b..906f9d84ba9 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -532,6 +532,11 @@ void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
// Does nothing if we don't have a remote player
}
+void BrowserMediaPlayerManager::OnRequestRemotePlaybackStop(
+ int /* player_id */) {
+ // Does nothing if we don't have a remote player
+}
+
bool BrowserMediaPlayerManager::IsPlayingRemotely(int player_id) {
return false;
}
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.h b/chromium/content/browser/media/android/browser_media_player_manager.h
index e9f57e31018..6d50830c8c1 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -28,7 +28,6 @@ namespace content {
#if !defined(USE_AURA)
class ContentViewCore;
#endif
-class ExternalVideoSurfaceContainer;
class RenderFrameHost;
class WebContents;
@@ -113,6 +112,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual void OnDestroyPlayer(int player_id);
virtual void OnRequestRemotePlayback(int player_id);
virtual void OnRequestRemotePlaybackControl(int player_id);
+ virtual void OnRequestRemotePlaybackStop(int player_id);
virtual bool IsPlayingRemotely(int player_id);
virtual void ReleaseFullscreenPlayer(media::MediaPlayerAndroid* player);
diff --git a/chromium/content/browser/media/android/browser_media_session_manager.cc b/chromium/content/browser/media/android/browser_media_session_manager.cc
deleted file mode 100644
index a3c15f2b250..00000000000
--- a/chromium/content/browser/media/android/browser_media_session_manager.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/browser_media_session_manager.h"
-
-#include "base/optional.h"
-#include "content/browser/media/session/media_session.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/media/media_metadata_sanitizer.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/media_metadata.h"
-
-namespace content {
-
-BrowserMediaSessionManager::BrowserMediaSessionManager(
- RenderFrameHost* render_frame_host)
- : render_frame_host_(render_frame_host) {}
-
-void BrowserMediaSessionManager::OnSetMetadata(
- int session_id,
- const base::Optional<MediaMetadata>& insecure_metadata) {
- // When receiving a MediaMetadata, the browser process can't trust that it is
- // coming from a known and secure source. It must be processed accordingly.
- if (insecure_metadata.has_value() &&
- !MediaMetadataSanitizer::CheckSanity(insecure_metadata.value())) {
- render_frame_host_->GetProcess()->ShutdownForBadMessage(
- RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
- return;
- }
-
- NOTIMPLEMENTED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/android/browser_media_session_manager.h b/chromium/content/browser/media/android/browser_media_session_manager.h
deleted file mode 100644
index 9d9253b39c8..00000000000
--- a/chromium/content/browser/media/android/browser_media_session_manager.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "content/common/content_export.h"
-
-namespace IPC {
-class Message;
-} // namespace IPC
-
-namespace content {
-
-class RenderFrameHost;
-struct MediaMetadata;
-
-class CONTENT_EXPORT BrowserMediaSessionManager {
- public:
- explicit BrowserMediaSessionManager(RenderFrameHost* render_frame_host);
-
- virtual void OnSetMetadata(int session_id,
- const base::Optional<MediaMetadata>& metadata);
-
- private:
- RenderFrameHost* const render_frame_host_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserMediaSessionManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
diff --git a/chromium/content/browser/media/android/browser_media_session_manager_browsertest.cc b/chromium/content/browser/media/android/browser_media_session_manager_browsertest.cc
deleted file mode 100644
index b0892e68604..00000000000
--- a/chromium/content/browser/media/android/browser_media_session_manager_browsertest.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/browser_media_session_manager.h"
-
-#include <iostream>
-#include <sstream>
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/media/android/media_web_contents_observer_android.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/media_metadata.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Ne;
-
-namespace content {
-
-namespace {
-
-// Helper function for build test javascripts.
-std::string BuildSetMetadataScript(
- const base::Optional<MediaMetadata>& metadata) {
- std::ostringstream generated_script;
-
- generated_script
- << "var audio = document.createElement(\'audio\');"
- << "audio.session = new MediaSession();";
-
- if (!metadata.has_value()) {
- generated_script << "audio.session.metadata = null;";
- return generated_script.str();
- }
-
- generated_script
- << "audio.session.metadata = new MediaMetadata({"
- << "title: \"" << metadata->title << "\", "
- << "artist: \"" << metadata->artist << "\", "
- << "album: \"" << metadata->album << "\", "
- << "artwork: [";
-
- std::string artwork_separator = "";
- for (const auto& artwork : metadata->artwork) {
- generated_script << artwork_separator << "{"
- << "src: \"" << artwork.src.spec() << "\", "
- << "type: \"" << artwork.type << "\", "
- << "sizes: \"";
- for (const auto& size : artwork.sizes) {
- generated_script << size.width() << "x" << size.height() << " ";
- }
- generated_script << "\"}";
- artwork_separator = ", ";
- }
- generated_script << "]});";
-
- return generated_script.str();
-}
-
-} // anonymous namespace
-
-// Helper function to be pretty-print error messages by GMock.
-void PrintTo(const base::Optional<MediaMetadata>& metadata, std::ostream* os) {
- if (!metadata.has_value()) {
- *os << "<null MediaMetadata>";
- return;
- }
-
- *os << "{ title=" << metadata->title << ", ";
- *os << "artist=" << metadata->artist << ", ";
- *os << "album=" << metadata->album << ", ";
- *os << "artwork=[";
- for (const auto& artwork : metadata->artwork) {
- *os << "{ src=" << artwork.src.spec() << ", ";
- *os << "type=" << artwork.type << ", ";
- *os << "sizes=[";
- for (const auto& size : artwork.sizes) {
- *os << size.width() << "x" << size.height() << " ";
- }
- *os << "]}";
- }
- *os << "]}";
-}
-
-class MockBrowserMediaSessionManager : public BrowserMediaSessionManager {
- public:
- explicit MockBrowserMediaSessionManager(RenderFrameHost* render_frame_host)
- : BrowserMediaSessionManager(render_frame_host) {}
-
- MOCK_METHOD2(OnSetMetadata, void(
- int session_id, const base::Optional<MediaMetadata>& metadata));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockBrowserMediaSessionManager);
-};
-
-class BrowserMediaSessionManagerBrowserTest : public ContentBrowserTest {
- public:
- BrowserMediaSessionManagerBrowserTest() = default;
- ~BrowserMediaSessionManagerBrowserTest() override = default;
-
- protected:
- void SetUpOnMainThread() override {
- ContentBrowserTest::SetUpOnMainThread();
- web_contents_ = shell()->web_contents();
-
- std::unique_ptr<MockBrowserMediaSessionManager> manager(
- new MockBrowserMediaSessionManager(web_contents_->GetMainFrame()));
- browser_media_session_manager_ = manager.get();
- MediaWebContentsObserverAndroid::FromWebContents(web_contents_)
- ->SetMediaSessionManagerForTest(
- web_contents_->GetMainFrame(), std::move(manager));
-
- shell()->LoadURL(GURL("about:blank"));
-
- ON_CALL(*browser_media_session_manager_, OnSetMetadata(_, _))
- .WillByDefault(InvokeWithoutArgs([&]{
- message_loop_runner_->Quit();
- }));
- }
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(
- switches::kEnableBlinkFeatures, "MediaSession");
- }
-
- WebContents* web_contents_;
- MockBrowserMediaSessionManager* browser_media_session_manager_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
-};
-
-IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest,
- TestMetadataPropagated) {
- base::Optional<MediaMetadata> expected = MediaMetadata();
- expected->title = base::ASCIIToUTF16("title1");
- expected->artist = base::ASCIIToUTF16("artist1");
- expected->album = base::ASCIIToUTF16("album1");
- MediaMetadata::Artwork artwork;
- artwork.src = GURL("http://foo.com/bar.png");
- artwork.type = base::ASCIIToUTF16("image/png");
- artwork.sizes.push_back(gfx::Size(128, 128));
- expected->artwork.push_back(artwork);
-
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(expected)));
- message_loop_runner_->Run();
-}
-
-IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest,
- TestSetMetadataTwice) {
- // Make expectations ordered.
- InSequence s;
-
- base::Optional<MediaMetadata> dont_care_metadata = MediaMetadata();
-
- base::Optional<MediaMetadata> expected = MediaMetadata();
- expected->title = base::ASCIIToUTF16("title2");
- expected->artist = base::ASCIIToUTF16("artist2");
- expected->album = base::ASCIIToUTF16("album2");
- MediaMetadata::Artwork artwork;
- artwork.src = GURL("http://foo.com/bar.jpg");
- artwork.type = base::ASCIIToUTF16("image/jpeg");
- artwork.sizes.push_back(gfx::Size(256, 256));
- expected->artwork.push_back(artwork);
-
- // Set metadata for the first time.
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_,
- OnSetMetadata(_, dont_care_metadata))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(dont_care_metadata)));
- message_loop_runner_->Run();
-
- // Set metadata for the second time.
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(expected)));
- message_loop_runner_->Run();
-}
-
-
-IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest,
- TestNullMetadata) {
- // Make expectations ordered.
- InSequence s;
-
- base::Optional<MediaMetadata> dont_care_metadata = MediaMetadata();
-
- base::Optional<MediaMetadata> expected;
-
- // Set metadata for the first time.
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_,
- OnSetMetadata(_, dont_care_metadata))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(dont_care_metadata)));
- message_loop_runner_->Run();
-
- // Set metadata for the second time.
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(expected)));
- message_loop_runner_->Run();
-}
-
-IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest,
- TestFileArtworkRemoved) {
- // Make expectations ordered.
- InSequence s;
-
- base::Optional<MediaMetadata> dirty_metadata = MediaMetadata();
- MediaMetadata::Artwork file_artwork;
- file_artwork.src = GURL("file:///foo/bar.jpg");
- file_artwork.type = base::ASCIIToUTF16("image/jpeg");
- dirty_metadata->artwork.push_back(file_artwork);
-
- base::Optional<MediaMetadata> expected = MediaMetadata();
-
- // Set metadata for the first time.
- message_loop_runner_ = new MessageLoopRunner();
- EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected))
- .Times(1);
- ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(),
- BuildSetMetadataScript(dirty_metadata)));
- message_loop_runner_->Run();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/android/browser_surface_view_manager.cc b/chromium/content/browser/media/android/browser_surface_view_manager.cc
index 405f2281277..7ce80ecbcc3 100644
--- a/chromium/content/browser/media/android/browser_surface_view_manager.cc
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.cc
@@ -6,14 +6,13 @@
#include "base/android/build_info.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/android/child_process_launcher_android.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/surface_view_manager_messages_android.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "media/base/surface_manager.h"
#include "ui/gfx/geometry/size.h"
@@ -41,23 +40,24 @@ void BrowserSurfaceViewManager::SetVideoSurface(gl::ScopedJavaSurface surface) {
TRACE_EVENT0("media", "BrowserSurfaceViewManager::SetVideoSurface");
if (surface.IsEmpty()) {
DCHECK_NE(surface_id_, media::SurfaceManager::kNoSurfaceID);
- GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
- UnregisterViewSurface(surface_id_);
- SendDestroyingVideoSurfaceIfRequired(surface_id_);
+ gpu::GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
+ gpu::GpuSurfaceTracker::Get()->UnregisterViewSurface(surface_id_);
+ SendDestroyingVideoSurface(surface_id_);
surface_id_ = media::SurfaceManager::kNoSurfaceID;
} else {
- // We mainly use the surface tracker to allocate a surface id for us. The
+ // We just use the surface tracker to allocate a surface id for us. The
// lookup will go through the Android specific path and get the java
// surface directly, so there's no need to add a valid native widget here.
- surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
+ surface_id_ = gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
gfx::kNullAcceleratedWidget);
- RegisterViewSurface(surface_id_, surface.j_surface());
+ gpu::GpuSurfaceTracker::GetInstance()->RegisterViewSurface(
+ surface_id_, surface.j_surface());
SendSurfaceID(surface_id_);
}
}
void BrowserSurfaceViewManager::DidExitFullscreen(bool release_media_player) {
- DVLOG(3) << __FUNCTION__;
+ DVLOG(3) << __func__;
content_video_view_.reset();
}
@@ -104,13 +104,7 @@ bool BrowserSurfaceViewManager::SendSurfaceID(int surface_id) {
render_frame_host_->GetRoutingID(), surface_id));
}
-void BrowserSurfaceViewManager::SendDestroyingVideoSurfaceIfRequired(
- int surface_id) {
- // Only send the surface destruction message on JB, where not doing it can
- // cause a crash.
- if (base::android::BuildInfo::GetInstance()->sdk_int() >= 18)
- return;
-
+void BrowserSurfaceViewManager::SendDestroyingVideoSurface(int surface_id) {
base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
// Unretained is okay because we're waiting on the callback.
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 f32f6b888ce..a15e52e3985 100644
--- a/chromium/content/browser/media/android/browser_surface_view_manager.h
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.h
@@ -41,10 +41,8 @@ class CONTENT_EXPORT BrowserSurfaceViewManager
// Synchronously notify the decoder that the surface is being destroyed so it
// can stop rendering to it. This sends a message to the GPU process. Without
// this, the MediaCodec decoder will start throwing IllegalStateException, and
- // crash on some devices (http://crbug.com/598408). There is no way for us to
- // make sure the surface outlives the decoder because Android initiates the
- // destruction in some cases.
- void SendDestroyingVideoSurfaceIfRequired(int surface_id);
+ // crash on some devices (http://crbug.com/598408, http://crbug.com/600454).
+ void SendDestroyingVideoSurface(int surface_id);
RenderFrameHost* const 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 62ae926689c..d2270009b28 100644
--- a/chromium/content/browser/media/android/media_player_renderer.cc
+++ b/chromium/content/browser/media/android/media_player_renderer.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/callback_helpers.h"
#include "content/browser/android/scoped_surface_request_manager.h"
#include "content/browser/media/android/media_resource_getter_impl.h"
#include "content/public/browser/browser_context.h"
@@ -14,6 +15,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
+#include "media/base/android/media_service_throttler.h"
// TODO(tguilbert): Remove this ID once MediaPlayerManager has been deleted
// and MediaPlayerBridge updated. See comment in header file.
@@ -21,6 +23,12 @@ constexpr int kUnusedAndIrrelevantPlayerId = 0;
namespace content {
+namespace {
+
+media::MediaUrlInterceptor* g_media_url_interceptor = nullptr;
+
+} // namespace
+
MediaPlayerRenderer::MediaPlayerRenderer(RenderFrameHost* render_frame_host)
: render_frame_host_(render_frame_host),
has_error_(false),
@@ -35,6 +43,11 @@ void MediaPlayerRenderer::Initialize(
media::RendererClient* client,
const media::PipelineStatusCB& init_cb) {
DVLOG(1) << __func__;
+
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ renderer_client_ = client;
+
if (demuxer_stream_provider->GetType() !=
media::DemuxerStreamProvider::Type::URL) {
DLOG(ERROR) << "DemuxerStreamProvider is not of Type URL";
@@ -42,22 +55,37 @@ void MediaPlayerRenderer::Initialize(
return;
}
- GURL url = demuxer_stream_provider->GetUrl();
- renderer_client_ = client;
+ base::TimeDelta creation_delay =
+ media::MediaServiceThrottler::GetInstance()->GetDelayForClientCreation();
+
+ if (creation_delay.is_zero()) {
+ CreateMediaPlayer(demuxer_stream_provider->GetMediaUrlParams(), init_cb);
+ return;
+ }
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&MediaPlayerRenderer::CreateMediaPlayer,
+ weak_factory_.GetWeakPtr(),
+ demuxer_stream_provider->GetMediaUrlParams(), init_cb),
+ creation_delay);
+}
+
+void MediaPlayerRenderer::CreateMediaPlayer(
+ const media::MediaUrlParams& url_params,
+ const media::PipelineStatusCB& init_cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
const std::string user_agent = GetContentClient()->GetUserAgent();
- // TODO(tguilbert): Get the first party cookies from WMPI. See
- // crbug.com/636604.
media_player_.reset(new media::MediaPlayerBridge(
- kUnusedAndIrrelevantPlayerId, url,
- GURL(), // first_party_for_cookies
- user_agent,
+ kUnusedAndIrrelevantPlayerId, url_params.media_url,
+ url_params.first_party_for_cookies, user_agent,
false, // hide_url_log
this, base::Bind(&MediaPlayerRenderer::OnDecoderResourcesReleased,
weak_factory_.GetWeakPtr()),
GURL(), // frame_url
- false)); // allow_crendentials
+ true)); // allow_crendentials
media_player_->Initialize();
init_cb.Run(media::PIPELINE_OK);
@@ -81,6 +109,18 @@ void MediaPlayerRenderer::StartPlayingFrom(base::TimeDelta time) {
media_player_->Start();
media_player_->SeekTo(time);
+
+ // WMPI needs to receive a BUFFERING_HAVE_ENOUGH data before sending a
+ // playback_rate > 0. The MediaPlayer manages its own buffering and will pause
+ // internally if ever it runs out of data. Sending BUFFERING_HAVE_ENOUGH here
+ // is always safe.
+ //
+ // NOTE: OnBufferingUpdate is triggered whenever the media has buffered or
+ // played up to a % value between 1-100, and it's not a reliable indicator of
+ // the buffering state.
+ //
+ // TODO(tguilbert): Investigate the effect of this call on UMAs.
+ renderer_client_->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH);
}
void MediaPlayerRenderer::SetPlaybackRate(double playback_rate) {
@@ -153,9 +193,7 @@ media::MediaResourceGetter* MediaPlayerRenderer::GetMediaResourceGetter() {
}
media::MediaUrlInterceptor* MediaPlayerRenderer::GetMediaUrlInterceptor() {
- // TODO(tguilbert): Offer a RegisterMediaUrlInterceptor equivalent for use in
- // webview. See crbug.com/636588.
- return nullptr;
+ return g_media_url_interceptor;
}
void MediaPlayerRenderer::OnTimeUpdate(int player_id,
@@ -182,15 +220,7 @@ void MediaPlayerRenderer::OnPlaybackComplete(int player_id) {
void MediaPlayerRenderer::OnMediaInterrupted(int player_id) {}
-void MediaPlayerRenderer::OnBufferingUpdate(int player_id, int percentage) {
- // As per Android documentation, |percentage| actually indicates "percentage
- // buffered or played". E.g. if we are at 50% playback and have 1%
- // buffered, |percentage| will be equal to 51.
- //
- // MediaPlayer manages its own buffering and will pause internally if ever it
- // runs out of data. Therefore, we can always return BUFFERING_HAVE_ENOUGH.
- renderer_client_->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH);
-}
+void MediaPlayerRenderer::OnBufferingUpdate(int player_id, int percentage) {}
void MediaPlayerRenderer::OnSeekComplete(int player_id,
const base::TimeDelta& current_time) {}
@@ -240,6 +270,12 @@ void MediaPlayerRenderer::OnDecoderResourcesReleased(int player_id) {
// See crbug.com/636615.
}
+// static
+void MediaPlayerRenderer::RegisterMediaUrlInterceptor(
+ media::MediaUrlInterceptor* media_url_interceptor) {
+ g_media_url_interceptor = media_url_interceptor;
+}
+
void MediaPlayerRenderer::CancelScopedSurfaceRequest() {
if (!surface_request_token_)
return;
diff --git a/chromium/content/browser/media/android/media_player_renderer.h b/chromium/content/browser/media/android/media_player_renderer.h
index bd27299df1b..2ff25839766 100644
--- a/chromium/content/browser/media/android/media_player_renderer.h
+++ b/chromium/content/browser/media/android/media_player_renderer.h
@@ -38,6 +38,10 @@ namespace content {
class CONTENT_EXPORT MediaPlayerRenderer : public media::Renderer,
public media::MediaPlayerManager {
public:
+ // Permits embedders to handle custom urls.
+ static void RegisterMediaUrlInterceptor(
+ media::MediaUrlInterceptor* media_url_interceptor);
+
explicit MediaPlayerRenderer(content::RenderFrameHost* render_frame_host);
~MediaPlayerRenderer() override;
@@ -96,6 +100,9 @@ class CONTENT_EXPORT MediaPlayerRenderer : public media::Renderer,
void OnScopedSurfaceRequestCompleted(gl::ScopedJavaSurface surface);
private:
+ void CreateMediaPlayer(const media::MediaUrlParams& params,
+ const media::PipelineStatusCB& init_cb);
+
// Used when creating |media_player_|.
void OnDecoderResourcesReleased(int player_id);
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 f131499a3c7..268e9095270 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.h
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.h
@@ -22,10 +22,6 @@ namespace storage {
class FileSystemContext;
}
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace content {
class BrowserContext;
diff --git a/chromium/content/browser/media/android/media_session_service_impl.cc b/chromium/content/browser/media/android/media_session_service_impl.cc
deleted file mode 100644
index 51e2799590d..00000000000
--- a/chromium/content/browser/media/android/media_session_service_impl.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/media_session_service_impl.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/media/android/browser_media_session_manager.h"
-#include "content/browser/media/android/media_web_contents_observer_android.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/media_metadata.h"
-
-namespace content {
-
-MediaSessionServiceImpl::MediaSessionServiceImpl(
- RenderFrameHost* render_frame_host)
- : render_frame_host_(render_frame_host) {}
-
-MediaSessionServiceImpl::~MediaSessionServiceImpl() = default;
-
-// static
-void MediaSessionServiceImpl::Create(
- RenderFrameHost* render_frame_host,
- blink::mojom::MediaSessionServiceRequest request) {
- MediaSessionServiceImpl* impl =
- new MediaSessionServiceImpl(render_frame_host);
- impl->Bind(std::move(request));
-}
-
-void MediaSessionServiceImpl::SetMetadata(
- const base::Optional<content::MediaMetadata>& metadata) {
- WebContentsImpl* contents = static_cast<WebContentsImpl*>(
- WebContents::FromRenderFrameHost(render_frame_host_));
- DCHECK(contents);
- MediaWebContentsObserverAndroid::FromWebContents(contents)
- ->GetMediaSessionManager(render_frame_host_)
- ->OnSetMetadata(0, metadata);
-}
-
-void MediaSessionServiceImpl::Bind(
- blink::mojom::MediaSessionServiceRequest request) {
- binding_.reset(new mojo::Binding<blink::mojom::MediaSessionService>(
- this, std::move(request)));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/android/media_web_contents_observer_android.cc b/chromium/content/browser/media/android/media_web_contents_observer_android.cc
index ae785f30fd8..cde2d8ecbea 100644
--- a/chromium/content/browser/media/android/media_web_contents_observer_android.cc
+++ b/chromium/content/browser/media/android/media_web_contents_observer_android.cc
@@ -8,7 +8,6 @@
#include "base/memory/ptr_util.h"
#include "content/browser/media/android/browser_media_player_manager.h"
-#include "content/browser/media/android/browser_media_session_manager.h"
#include "content/browser/media/android/browser_surface_view_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
@@ -54,19 +53,6 @@ MediaWebContentsObserverAndroid::GetMediaPlayerManager(
return manager;
}
-BrowserMediaSessionManager*
-MediaWebContentsObserverAndroid::GetMediaSessionManager(
- RenderFrameHost* render_frame_host) {
- auto it = media_session_managers_.find(render_frame_host);
- if (it != media_session_managers_.end())
- return it->second;
-
- BrowserMediaSessionManager* manager =
- new BrowserMediaSessionManager(render_frame_host);
- media_session_managers_.set(render_frame_host, base::WrapUnique(manager));
- return manager;
-}
-
BrowserSurfaceViewManager*
MediaWebContentsObserverAndroid::GetSurfaceViewManager(
RenderFrameHost* render_frame_host) {
@@ -80,12 +66,6 @@ MediaWebContentsObserverAndroid::GetSurfaceViewManager(
return manager;
}
-void MediaWebContentsObserverAndroid::SetMediaSessionManagerForTest(
- RenderFrameHost* render_frame_host,
- std::unique_ptr<BrowserMediaSessionManager> manager) {
- media_session_managers_.set(render_frame_host, std::move(manager));
-}
-
void MediaWebContentsObserverAndroid::SuspendAllMediaPlayers() {
web_contents()->ForEachFrame(
base::Bind(&SuspendAllMediaPlayersInRenderFrame));
@@ -114,7 +94,6 @@ void MediaWebContentsObserverAndroid::RenderFrameDeleted(
MediaWebContentsObserver::RenderFrameDeleted(render_frame_host);
media_player_managers_.erase(render_frame_host);
- media_session_managers_.erase(render_frame_host);
surface_view_managers_.erase(render_frame_host);
}
@@ -172,6 +151,9 @@ bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
MediaPlayerHostMsg_RequestRemotePlaybackControl,
GetMediaPlayerManager(render_frame_host),
BrowserMediaPlayerManager::OnRequestRemotePlaybackControl)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_RequestRemotePlaybackStop,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnRequestRemotePlaybackStop)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
diff --git a/chromium/content/browser/media/android/media_web_contents_observer_android.h b/chromium/content/browser/media/android/media_web_contents_observer_android.h
index 7298f4fa2bc..14ea142526b 100644
--- a/chromium/content/browser/media/android/media_web_contents_observer_android.h
+++ b/chromium/content/browser/media/android/media_web_contents_observer_android.h
@@ -9,7 +9,6 @@
#include <memory>
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/common/content_export.h"
@@ -21,7 +20,6 @@ enum class MediaContentType;
namespace content {
class BrowserMediaPlayerManager;
-class BrowserMediaSessionManager;
class BrowserSurfaceViewManager;
// This class adds Android specific extensions to the MediaWebContentsObserver.
@@ -40,17 +38,9 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
// returned pointer.
BrowserMediaPlayerManager* GetMediaPlayerManager(
RenderFrameHost* render_frame_host);
- BrowserMediaSessionManager* GetMediaSessionManager(
- RenderFrameHost* render_frame_host);
BrowserSurfaceViewManager* GetSurfaceViewManager(
RenderFrameHost* render_frame_host);
- // Sets or overrides the BrowserMediaSessionManager for the given
- // |render_frame_host|.
- void SetMediaSessionManagerForTest(
- RenderFrameHost* render_frame_host,
- std::unique_ptr<BrowserMediaSessionManager> manager);
-
// Called by the WebContents when a tab has been closed but may still be
// available for "undo" -- indicates that all media players (even audio only
// players typically allowed background audio) bound to this WebContents must
@@ -90,12 +80,6 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
std::unique_ptr<BrowserMediaPlayerManager>>;
MediaPlayerManagerMap media_player_managers_;
- // Map from RenderFrameHost* to BrowserMediaSessionManager.
- using MediaSessionManagerMap =
- base::ScopedPtrHashMap<RenderFrameHost*,
- std::unique_ptr<BrowserMediaSessionManager>>;
- MediaSessionManagerMap media_session_managers_;
-
using SurfaceViewManagerMap =
base::ScopedPtrHashMap<RenderFrameHost*,
std::unique_ptr<BrowserSurfaceViewManager>>;
diff --git a/chromium/content/browser/media/android/provision_fetcher_impl.cc b/chromium/content/browser/media/android/provision_fetcher_impl.cc
deleted file mode 100644
index 896f373622f..00000000000
--- a/chromium/content/browser/media/android/provision_fetcher_impl.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/provision_fetcher_impl.h"
-
-#include "content/public/browser/android/provision_fetcher_factory.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/storage_partition.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace content {
-
-// static
-void ProvisionFetcherImpl::Create(
- RenderFrameHost* render_frame_host,
- media::mojom::ProvisionFetcherRequest request) {
- net::URLRequestContextGetter* context_getter =
- BrowserContext::GetDefaultStoragePartition(
- render_frame_host->GetProcess()->GetBrowserContext())->
- GetURLRequestContext();
- DCHECK(context_getter);
- mojo::MakeStrongBinding(base::MakeUnique<ProvisionFetcherImpl>(
- CreateProvisionFetcher(context_getter)),
- std::move(request));
-}
-
-ProvisionFetcherImpl::ProvisionFetcherImpl(
- std::unique_ptr<media::ProvisionFetcher> provision_fetcher)
- : provision_fetcher_(std::move(provision_fetcher)), weak_factory_(this) {
- DVLOG(1) << __FUNCTION__;
-}
-
-ProvisionFetcherImpl::~ProvisionFetcherImpl() {}
-
-void ProvisionFetcherImpl::Retrieve(const mojo::String& default_url,
- const mojo::String& request_data,
- const RetrieveCallback& callback) {
- DVLOG(1) << __FUNCTION__ << ": " << default_url;
- provision_fetcher_->Retrieve(
- default_url, request_data,
- base::Bind(&ProvisionFetcherImpl::OnResponse, weak_factory_.GetWeakPtr(),
- callback));
-}
-
-void ProvisionFetcherImpl::OnResponse(const RetrieveCallback& callback,
- bool success,
- const std::string& response) {
- DVLOG(1) << __FUNCTION__ << ": " << success;
- callback.Run(success, response);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/android/provision_fetcher_impl.h b/chromium/content/browser/media/android/provision_fetcher_impl.h
deleted file mode 100644
index fc1955742eb..00000000000
--- a/chromium/content/browser/media/android/provision_fetcher_impl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_PROVISION_FETCHER_IMPL_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_PROVISION_FETCHER_IMPL_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/android/provision_fetcher_factory.h"
-#include "media/base/android/provision_fetcher.h"
-#include "media/mojo/interfaces/provision_fetcher.mojom.h"
-
-namespace content {
-
-class RenderFrameHost;
-
-// A media::mojom::ProvisionFetcher implementation based on
-// media::ProvisionFetcher.
-class ProvisionFetcherImpl : public media::mojom::ProvisionFetcher {
- public:
- static void Create(RenderFrameHost* render_frame_host,
- media::mojom::ProvisionFetcherRequest request);
-
- explicit ProvisionFetcherImpl(
- std::unique_ptr<media::ProvisionFetcher> provision_fetcher);
- ~ProvisionFetcherImpl() override;
-
- // media::mojom::ProvisionFetcher implementation.
- void Retrieve(const mojo::String& default_url,
- const mojo::String& request_data,
- const RetrieveCallback& callback) final;
-
- private:
- // Callback for media::ProvisionFetcher::Retrieve().
- void OnResponse(const RetrieveCallback& callback,
- bool success,
- const std::string& response);
-
- std::unique_ptr<media::ProvisionFetcher> provision_fetcher_;
-
- base::WeakPtrFactory<ProvisionFetcherImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ProvisionFetcherImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_PROVISION_FETCHER_IMPL_H_
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
index b19e82ff462..ba86d56a8f0 100644
--- a/chromium/content/browser/media/audio_stream_monitor.cc
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -31,8 +31,8 @@ AudioStreamMonitor::AudioStreamMonitor(WebContents* contents)
: web_contents_(contents),
clock_(&default_tick_clock_),
was_recently_audible_(false),
- is_audible_(false)
-{
+ is_audible_(false),
+ active_streams_(0) {
DCHECK(web_contents_);
}
@@ -54,8 +54,6 @@ void AudioStreamMonitor::StartMonitoringStream(
int render_frame_id,
int stream_id,
const ReadPowerAndClipCallback& read_power_callback) {
- if (!monitoring_available())
- return;
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&StartMonitoringHelper,
@@ -69,8 +67,6 @@ void AudioStreamMonitor::StartMonitoringStream(
void AudioStreamMonitor::StopMonitoringStream(int render_process_id,
int render_frame_id,
int stream_id) {
- if (!media::AudioOutputController::will_monitor_audio_levels())
- return;
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&StopMonitoringHelper,
@@ -88,10 +84,16 @@ void AudioStreamMonitor::StartMonitoringHelper(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AudioStreamMonitor* const monitor =
AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
- if (monitor) {
- monitor->StartMonitoringStreamOnUIThread(
- render_process_id, stream_id, read_power_callback);
- }
+ if (!monitor)
+ return;
+
+ monitor->OnStreamAdded();
+
+ if (!power_level_monitoring_available())
+ return;
+
+ monitor->StartMonitoringStreamOnUIThread(render_process_id, stream_id,
+ read_power_callback);
}
// static
@@ -101,8 +103,15 @@ void AudioStreamMonitor::StopMonitoringHelper(int render_process_id,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AudioStreamMonitor* const monitor =
AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
- if (monitor)
- monitor->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
+ if (!monitor)
+ return;
+
+ monitor->OnStreamRemoved();
+
+ if (!power_level_monitoring_available())
+ return;
+
+ monitor->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
}
void AudioStreamMonitor::StartMonitoringStreamOnUIThread(
@@ -151,7 +160,7 @@ void AudioStreamMonitor::Poll() {
}
if (is_audible_ != was_audible)
- web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ web_contents_->OnAudioStateChanged(is_audible_);
}
void AudioStreamMonitor::MaybeToggle() {
@@ -176,4 +185,32 @@ void AudioStreamMonitor::MaybeToggle() {
}
}
+void AudioStreamMonitor::OnStreamAdded() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ++active_streams_;
+
+ if (power_level_monitoring_available())
+ return;
+
+ if (active_streams_ == 1) {
+ is_audible_ = true;
+ web_contents_->OnAudioStateChanged(true);
+ MaybeToggle();
+ }
+}
+
+void AudioStreamMonitor::OnStreamRemoved() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ --active_streams_;
+
+ if (power_level_monitoring_available())
+ return;
+
+ if (active_streams_ == 0) {
+ is_audible_ = false;
+ web_contents_->OnAudioStateChanged(false);
+ MaybeToggle();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/audio_stream_monitor.h b/chromium/content/browser/media/audio_stream_monitor.h
index 12f06055c54..ced46683efb 100644
--- a/chromium/content/browser/media/audio_stream_monitor.h
+++ b/chromium/content/browser/media/audio_stream_monitor.h
@@ -34,18 +34,15 @@ class WebContents;
// to turn on/off repeatedly and annoy the user. AudioStreamMonitor sends UI
// update notifications only when needed, but may be queried at any time.
//
+// When power level monitoring is not available, audibility is approximated
+// with having active audio streams.
+//
// Each WebContentsImpl owns an AudioStreamMonitor.
class CONTENT_EXPORT AudioStreamMonitor {
public:
explicit AudioStreamMonitor(WebContents* contents);
~AudioStreamMonitor();
- // Indicates if audio stream monitoring is available. It's only available if
- // AudioOutputController can and will monitor output power levels.
- static bool monitoring_available() {
- return media::AudioOutputController::will_monitor_audio_levels();
- }
-
// Returns true if audio has recently been audible from the tab. This is
// usually called whenever the tab data model is refreshed; but there are
// other use cases as well (e.g., the OOM killer uses this to de-prioritize
@@ -89,6 +86,13 @@ class CONTENT_EXPORT AudioStreamMonitor {
kHoldOnMilliseconds = 2000
};
+ // Indicates if monitoring of audio stream power level is available.
+ // It's only available if AudioOutputController can and will monitor
+ // output power levels.
+ static bool power_level_monitoring_available() {
+ return media::AudioOutputController::will_monitor_audio_levels();
+ }
+
// Helper methods for starting and stopping monitoring which lookup the
// identified renderer and forward calls to the correct AudioStreamMonitor.
static void StartMonitoringHelper(
@@ -119,6 +123,11 @@ class CONTENT_EXPORT AudioStreamMonitor {
// on, |off_timer_| is started to re-invoke this method in the future.
void MaybeToggle();
+ // Helper functions to track number of active streams when power level
+ // monitoring is not available.
+ void OnStreamAdded();
+ void OnStreamRemoved();
+
// The WebContents instance to receive indicator toggle notifications. This
// pointer should be valid for the lifetime of AudioStreamMonitor.
WebContents* const web_contents_;
@@ -154,6 +163,10 @@ class CONTENT_EXPORT AudioStreamMonitor {
// future.
base::OneShotTimer off_timer_;
+ // Number of active streams to be used as a proxy for audibility when power
+ // level monitoring is not available.
+ size_t active_streams_;
+
DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitor);
};
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index 2b883521e5c..94e796fd49d 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -10,9 +10,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
-#include "content/browser/browser_thread_impl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/base/audio_parameters.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -108,9 +107,10 @@ class AudioMirroringManagerTest : public testing::Test {
typedef AudioMirroringManager::StreamRoutes StreamRoutes;
AudioMirroringManagerTest()
- : io_thread_(BrowserThread::IO, &message_loop_),
- params_(AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
- AudioParameters::kAudioCDSampleRate, 16,
+ : params_(AudioParameters::AUDIO_FAKE,
+ media::CHANNEL_LAYOUT_STEREO,
+ AudioParameters::kAudioCDSampleRate,
+ 16,
AudioParameters::kAudioCDSampleRate / 10) {}
MockDiverter* CreateStream(int render_process_id,
@@ -207,8 +207,7 @@ class AudioMirroringManagerTest : public testing::Test {
}
private:
- base::MessageLoopForIO message_loop_;
- BrowserThreadImpl io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
AudioParameters params_;
AudioMirroringManager mirroring_manager_;
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 0878419cb60..561e68a6f50 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.cc
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
@@ -16,10 +16,10 @@
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
#include "device/power_save_blocker/power_save_blocker.h"
-#include "media/base/video_capture_types.h"
#include "media/base/video_util.h"
#include "media/capture/content/thread_safe_capture_oracle.h"
#include "media/capture/content/video_capture_oracle.h"
+#include "media/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/screen_position_client.h"
@@ -211,10 +211,10 @@ 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(base::Bind(
- &AuraWindowCaptureMachine::DidCopyOutput,
- weak_factory_.GetWeakPtr(), frame, event_time, start_time,
- capture_frame_cb));
+ cc::CopyOutputRequest::CreateRequest(
+ base::Bind(&AuraWindowCaptureMachine::DidCopyOutput,
+ weak_factory_.GetWeakPtr(), std::move(frame), event_time,
+ start_time, capture_frame_cb));
gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(),
desktop_window_->bounds().height());
request->set_area(window_rect);
@@ -260,7 +260,7 @@ void AuraWindowCaptureMachine::DidCopyOutput(
// If ProcessCopyOutputResponse() failed, it will not run |capture_frame_cb|,
// so do that now.
if (!succeeded)
- capture_frame_cb.Run(video_frame, event_time, false);
+ capture_frame_cb.Run(std::move(video_frame), event_time, false);
}
bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
@@ -351,7 +351,7 @@ void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
base::WeakPtr<AuraWindowCaptureMachine> machine,
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
- const scoped_refptr<media::VideoFrame>& target,
+ scoped_refptr<media::VideoFrame> target,
std::unique_ptr<cc::SingleReleaseCallback> release_callback,
bool result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -369,7 +369,7 @@ void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
result = false;
}
- capture_frame_cb.Run(target, event_time, result);
+ capture_frame_cb.Run(std::move(target), event_time, result);
}
void AuraWindowCaptureMachine::OnWindowBoundsChanged(
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 ff2334398db..40344e4d6fe 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.h
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.h
@@ -103,7 +103,7 @@ class AuraWindowCaptureMachine
base::WeakPtr<AuraWindowCaptureMachine> machine,
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
- const scoped_refptr<media::VideoFrame>& target,
+ scoped_refptr<media::VideoFrame> target,
std::unique_ptr<cc::SingleReleaseCallback> release_callback,
bool result);
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.cc b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
index b4a2ba5a4a1..f78e56c3451 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
@@ -109,6 +109,11 @@ bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
return false;
}
aura::Window* active_window = activation_client->GetActiveWindow();
+ if (!active_window) {
+ DVLOG(2) << "Skipping update as there is no active window";
+ Clear();
+ return false;
+ }
if (!active_window->Contains(window_)) {
// Return early if the target window is not active.
DVLOG(2) << "Skipping update on an inactive window";
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index cde383dc50a..209b1c14762 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -22,6 +23,7 @@
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
+#include "content/public/common/content_switches.h"
#include "device/power_save_blocker/power_save_blocker.h"
#include "media/base/video_util.h"
#include "media/capture/content/capture_resolution_chooser.h"
@@ -32,7 +34,6 @@
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
-#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
namespace content {
@@ -61,6 +62,11 @@ bool IsFrameUnpackedOrInverted(webrtc::DesktopFrame* frame) {
} // namespace
+#if defined(OS_WIN)
+const base::Feature kDirectXCapturer{"DirectXCapturer",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
public:
Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
@@ -349,7 +355,7 @@ void DesktopCaptureDevice::Core::DoCapture() {
DCHECK(!capture_in_progress_);
capture_in_progress_ = true;
- desktop_capturer_->Capture(webrtc::DesktopRegion());
+ desktop_capturer_->CaptureFrame();
// Currently only synchronous implementations of DesktopCapturer are
// supported.
@@ -365,47 +371,46 @@ std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
options.set_disable_effects(false);
#if defined(OS_WIN)
- options.set_allow_use_magnification_api(true);
+ if (!base::FeatureList::IsEnabled(kDirectXCapturer)) {
+ options.set_allow_use_magnification_api(true);
+ } else {
+ options.set_allow_directx_capturer(true);
+ options.set_allow_use_magnification_api(false);
+ }
#endif
- std::unique_ptr<webrtc::DesktopCapturer> capturer;
-
- switch (source.type) {
- case DesktopMediaID::TYPE_SCREEN: {
- std::unique_ptr<webrtc::ScreenCapturer> screen_capturer(
- webrtc::ScreenCapturer::Create(options));
- if (screen_capturer && screen_capturer->SelectScreen(source.id)) {
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- screen_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForScreen(options,
- source.id)));
- IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
- if (source.audio_share) {
- IncrementDesktopCaptureCounter(
- SCREEN_CAPTURER_CREATED_WITH_AUDIO);
- } else {
- IncrementDesktopCaptureCounter(
- SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
- }
- }
- break;
- }
-
- case DesktopMediaID::TYPE_WINDOW: {
- std::unique_ptr<webrtc::WindowCapturer> window_capturer(
- webrtc::CroppingWindowCapturer::Create(options));
- if (window_capturer && window_capturer->SelectWindow(source.id)) {
- window_capturer->BringSelectedWindowToFront();
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- window_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForWindow(options,
- source.id)));
- IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
- }
- break;
- }
-
- default: { NOTREACHED(); }
+ std::unique_ptr<webrtc::DesktopCapturer> capturer;
+
+ switch (source.type) {
+ case DesktopMediaID::TYPE_SCREEN: {
+ std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
+ webrtc::DesktopCapturer::CreateScreenCapturer(options));
+ if (screen_capturer && screen_capturer->SelectSource(source.id)) {
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ screen_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForScreen(options, source.id)));
+ IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
+ IncrementDesktopCaptureCounter(
+ source.audio_share ? SCREEN_CAPTURER_CREATED_WITH_AUDIO
+ : SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
+ }
+ break;
+ }
+
+ case DesktopMediaID::TYPE_WINDOW: {
+ std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
+ webrtc::CroppingWindowCapturer::Create(options));
+ if (window_capturer && window_capturer->SelectSource(source.id)) {
+ window_capturer->FocusOnSelectedSource();
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ window_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
+ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
+ }
+ break;
+ }
+
+ default: { NOTREACHED(); }
}
std::unique_ptr<media::VideoCaptureDevice> result;
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.h b/chromium/content/browser/media/capture/desktop_capture_device.h
index 2cb77e668bd..033cc20657b 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device.h
@@ -16,7 +16,6 @@
#include "ui/gfx/native_widget_types.h"
namespace base {
-class SingleThreadTaskRunner;
class Thread;
} // namespace base
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.h b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
index 73a7d53761c..a3a93747225 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
@@ -14,10 +14,6 @@
#include "media/capture/content/screen_capture_device_core.h"
#include "media/capture/video/video_capture_device.h"
-namespace aura {
-class Window;
-} // namespace aura
-
namespace content {
// An implementation of VideoCaptureDevice that mirrors an Aura window.
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
index cca139f7333..a5bba004c8b 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -11,12 +11,12 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/desktop_media_id.h"
-#include "media/base/video_capture_types.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/test/aura_test_helper.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
@@ -74,7 +74,7 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override {
+ scoped_refptr<media::VideoFrame> frame) override {
DoOnIncomingCapturedVideoFrame();
}
std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
@@ -92,9 +92,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
// Test harness that sets up a minimal environment with necessary stubs.
class DesktopCaptureDeviceAuraTest : public testing::Test {
public:
- DesktopCaptureDeviceAuraTest()
- : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
- ~DesktopCaptureDeviceAuraTest() override {}
+ DesktopCaptureDeviceAuraTest() = default;
+ ~DesktopCaptureDeviceAuraTest() override = default;
protected:
void SetUp() override {
@@ -102,7 +101,8 @@ class DesktopCaptureDeviceAuraTest : public testing::Test {
bool enable_pixel_output = false;
ui::ContextFactory* context_factory =
ui::InitializeContextFactoryForTests(enable_pixel_output);
- helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
+ helper_.reset(
+ new aura::test::AuraTestHelper(base::MessageLoopForUI::current()));
helper_->SetUp(context_factory);
new wm::DefaultActivationClient(helper_->root_window());
@@ -131,8 +131,7 @@ class DesktopCaptureDeviceAuraTest : public testing::Test {
aura::Window* root_window() { return helper_->root_window(); }
private:
- base::MessageLoopForUI message_loop_;
- BrowserThreadImpl browser_thread_for_ui_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<aura::test::AuraTestHelper> helper_;
std::unique_ptr<aura::Window> desktop_window_;
std::unique_ptr<aura::test::TestWindowDelegate> window_delegate_;
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
index 63f655f4b34..da791c2e437 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -19,9 +19,9 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
-#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
using ::testing::_;
using ::testing::AnyNumber;
@@ -93,7 +93,7 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override {
+ scoped_refptr<media::VideoFrame> frame) override {
DoOnIncomingCapturedVideoFrame();
}
std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
@@ -171,7 +171,7 @@ class UnpackedDesktopFrame : public webrtc::DesktopFrame {
};
// TODO(sergeyu): Move this to a separate file where it can be reused.
-class FakeScreenCapturer : public webrtc::ScreenCapturer {
+class FakeScreenCapturer : public webrtc::DesktopCapturer {
public:
FakeScreenCapturer()
: callback_(NULL),
@@ -192,7 +192,7 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
// VideoFrameCapturer interface.
void Start(Callback* callback) override { callback_ = callback; }
- void Capture(const webrtc::DesktopRegion& region) override {
+ void CaptureFrame() override {
webrtc::DesktopSize size;
if (frame_index_ % 2 == 0) {
size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
@@ -212,9 +212,9 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
std::move(frame));
}
- bool GetScreenList(ScreenList* screens) override { return false; }
+ bool GetSourceList(SourceList* screens) override { return false; }
- bool SelectScreen(webrtc::ScreenId id) override { return false; }
+ bool SelectSource(SourceId id) override { return false; }
private:
Callback* callback_;
@@ -285,7 +285,7 @@ class DesktopCaptureDeviceTest : public testing::Test {
#endif
TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
std::unique_ptr<webrtc::DesktopCapturer> capturer(
- webrtc::ScreenCapturer::Create(
+ webrtc::DesktopCapturer::CreateScreenCapturer(
webrtc::DesktopCaptureOptions::CreateDefault()));
CreateScreenCaptureDevice(std::move(capturer));
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android.h b/chromium/content/browser/media/capture/screen_capture_device_android.h
index 6c8e6879df5..09c899874d4 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android.h
+++ b/chromium/content/browser/media/capture/screen_capture_device_android.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "content/common/content_export.h"
#include "media/capture/content/screen_capture_device_core.h"
#include "media/capture/video/video_capture_device.h"
@@ -15,7 +16,8 @@ namespace content {
// ScreenCaptureDeviceAndroid is a forwarder to media::ScreenCaptureDeviceCore
// while keeping the Power Saving from kicking in between AllocateAndStart() and
// StopAndDeAllocate().
-class ScreenCaptureDeviceAndroid : public media::VideoCaptureDevice {
+class CONTENT_EXPORT ScreenCaptureDeviceAndroid
+ : public media::VideoCaptureDevice {
public:
ScreenCaptureDeviceAndroid();
~ScreenCaptureDeviceAndroid() override;
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
new file mode 100644
index 00000000000..f903f19f761
--- /dev/null
+++ b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
@@ -0,0 +1,99 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/screen_capture_device_android.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content {
+namespace {
+
+const int kFrameRate = 30;
+
+class MockDeviceClient : public media::VideoCaptureDevice::Client {
+ public:
+ MOCK_METHOD6(OnIncomingCapturedData,
+ void(const uint8_t* data,
+ int length,
+ const media::VideoCaptureFormat& frame_format,
+ int rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta tiemstamp));
+ MOCK_METHOD0(DoReserveOutputBuffer, void(void));
+ MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
+ MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
+ MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
+ MOCK_METHOD2(OnError,
+ void(const tracked_objects::Location& from_here,
+ const std::string& reason));
+ MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void));
+
+ // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
+ std::unique_ptr<Buffer> ReserveOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
+ EXPECT_EQ(media::PIXEL_STORAGE_CPU, storage);
+ DoReserveOutputBuffer();
+ return std::unique_ptr<Buffer>();
+ }
+ void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
+ const media::VideoCaptureFormat& frame_format,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override {
+ DoOnIncomingCapturedBuffer();
+ }
+ void OnIncomingCapturedVideoFrame(
+ std::unique_ptr<Buffer> buffer,
+ scoped_refptr<media::VideoFrame> frame) override {
+ DoOnIncomingCapturedVideoFrame();
+ }
+ std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
+ EXPECT_EQ(media::PIXEL_STORAGE_CPU, storage);
+ DoResurrectLastOutputBuffer();
+ return std::unique_ptr<Buffer>();
+ }
+};
+
+class ScreenCaptureDeviceAndroidTest : public testing::Test {
+ public:
+ ScreenCaptureDeviceAndroidTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDeviceAndroidTest);
+};
+
+TEST_F(ScreenCaptureDeviceAndroidTest, ConstructionDestruction) {
+ std::unique_ptr<media::VideoCaptureDevice> capture_device =
+ base::MakeUnique<ScreenCaptureDeviceAndroid>();
+}
+
+// Place holder. Currently user input result is required to start
+// MediaProjection, so we can't start a unittest that really starts capture.
+TEST_F(ScreenCaptureDeviceAndroidTest, DISABLED_StartAndStop) {
+ std::unique_ptr<media::VideoCaptureDevice> capture_device =
+ base::MakeUnique<ScreenCaptureDeviceAndroid>();
+ ASSERT_TRUE(capture_device);
+
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
+ EXPECT_CALL(*client, OnError(_, _)).Times(0);
+
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(640, 480);
+ capture_params.requested_format.frame_rate = kFrameRate;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_device->AllocateAndStart(capture_params, std::move(client));
+ capture_device->StopAndDeAllocate();
+}
+
+} // namespace
+} // namespace Content
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 39fc63cfe51..b9f15e6cd06 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
@@ -370,22 +370,19 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
const std::string& device_id,
const media::AudioParameters& params,
const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
- AudioMirroringManager* audio_mirroring_manager,
- bool is_duplication) {
- int render_process_id;
- int main_render_frame_id;
- if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget(
- device_id, &render_process_id, &main_render_frame_id)) {
+ AudioMirroringManager* audio_mirroring_manager) {
+ WebContentsMediaCaptureId media_id;
+ if (!WebContentsMediaCaptureId::Parse(device_id, &media_id)) {
return NULL;
}
return new WebContentsAudioInputStream(
- render_process_id, main_render_frame_id, audio_mirroring_manager,
- new WebContentsTracker(false),
+ media_id.render_process_id, media_id.main_render_frame_id,
+ audio_mirroring_manager, new WebContentsTracker(false),
new media::VirtualAudioInputStream(
params, worker_task_runner,
media::VirtualAudioInputStream::AfterCloseCallback()),
- is_duplication);
+ !media_id.disable_local_echo);
}
WebContentsAudioInputStream::WebContentsAudioInputStream(
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 1c444434767..dd2c0c29d3a 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
@@ -61,8 +61,7 @@ class CONTENT_EXPORT WebContentsAudioInputStream
const std::string& device_id,
const media::AudioParameters& params,
const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
- AudioMirroringManager* audio_mirroring_manager,
- bool is_duplication);
+ AudioMirroringManager* audio_mirroring_manager);
private:
friend class WebContentsAudioInputStreamTest;
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 e475cbd03d2..5212e7c1c8e 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
@@ -44,9 +44,6 @@
// In the above example, both capturing and rendering *each* take almost the
// full 33 ms available between frames, yet we see that the required throughput
// is obtained.
-//
-// Turning on verbose logging will cause the effective frame rate to be logged
-// at 5-second intervals.
#include "content/browser/media/capture/web_contents_video_capture_device.h"
@@ -63,7 +60,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
@@ -82,12 +78,12 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_media_capture_id.h"
#include "media/base/bind_to_current_loop.h"
-#include "media/base/video_capture_types.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_util.h"
#include "media/capture/content/screen_capture_device_core.h"
#include "media/capture/content/thread_safe_capture_oracle.h"
#include "media/capture/content/video_capture_oracle.h"
+#include "media/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -115,35 +111,16 @@ void DeleteOnWorkerThread(std::unique_ptr<base::Thread> render_thread,
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}
-// Responsible for logging the effective frame rate.
-class VideoFrameDeliveryLog {
- public:
- VideoFrameDeliveryLog();
-
- // Report that the frame posted with |frame_time| has been delivered.
- void ChronicleFrameDelivery(base::TimeTicks frame_time);
-
- private:
- // The following keep track of and log the effective frame rate whenever
- // verbose logging is turned on.
- base::TimeTicks last_frame_rate_log_time_;
- int count_frames_rendered_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog);
-};
-
// FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible
// with RenderWidgetHostViewFrameSubscriber. We create one per event type.
class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
public:
FrameSubscriber(media::VideoCaptureOracle::Event event_type,
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle,
- VideoFrameDeliveryLog* delivery_log,
base::WeakPtr<content::CursorRenderer> cursor_renderer,
base::WeakPtr<content::WindowActivityTracker> tracker)
: event_type_(event_type),
oracle_proxy_(oracle),
- delivery_log_(delivery_log),
cursor_renderer_(cursor_renderer),
window_activity_tracker_(tracker),
weak_ptr_factory_(this) {}
@@ -159,7 +136,7 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
base::WeakPtr<FrameSubscriber> frame_subscriber_,
const media::ThreadSafeCaptureOracle::CaptureFrameCallback&
capture_frame_cb,
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks timestamp,
const gfx::Rect& region_in_frame,
bool success);
@@ -169,7 +146,6 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
private:
const media::VideoCaptureOracle::Event event_type_;
scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
- VideoFrameDeliveryLog* const delivery_log_;
// We need a weak pointer since FrameSubscriber is owned externally and
// may outlive the cursor renderer.
base::WeakPtr<CursorRenderer> cursor_renderer_;
@@ -221,7 +197,6 @@ class ContentCaptureSubscription {
const int render_process_id_;
const int render_widget_id_;
- VideoFrameDeliveryLog delivery_log_;
std::unique_ptr<FrameSubscriber> refresh_subscriber_;
std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_;
CaptureCallback capture_callback_;
@@ -343,9 +318,6 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
// Video capture parameters that this machine is started with.
media::VideoCaptureParams capture_params_;
- // Last known RenderView size.
- gfx::Size last_view_size_;
-
// Responsible for forwarding events from the active RenderWidgetHost to the
// oracle, and initiating captures accordingly.
std::unique_ptr<ContentCaptureSubscription> subscription_;
@@ -379,8 +351,6 @@ bool FrameSubscriber::ShouldCaptureFrame(
*deliver_frame_cb =
base::Bind(&FrameSubscriber::DidCaptureFrame,
weak_ptr_factory_.GetWeakPtr(), capture_frame_cb, *storage);
- if (oracle_decision)
- delivery_log_->ChronicleFrameDelivery(present_time);
return oracle_decision;
}
@@ -388,7 +358,7 @@ void FrameSubscriber::DidCaptureFrame(
base::WeakPtr<FrameSubscriber> frame_subscriber_,
const media::ThreadSafeCaptureOracle::CaptureFrameCallback&
capture_frame_cb,
- const scoped_refptr<media::VideoFrame>& frame,
+ scoped_refptr<media::VideoFrame> frame,
base::TimeTicks timestamp,
const gfx::Rect& region_in_frame,
bool success) {
@@ -410,7 +380,7 @@ void FrameSubscriber::DidCaptureFrame(
frame_subscriber_->IsUserInteractingWithContent());
}
}
- capture_frame_cb.Run(frame, timestamp, success);
+ capture_frame_cb.Run(std::move(frame), timestamp, success);
}
bool FrameSubscriber::IsUserInteractingWithContent() {
@@ -439,7 +409,6 @@ ContentCaptureSubscription::ContentCaptureSubscription(
const CaptureCallback& capture_callback)
: render_process_id_(source.GetProcess()->GetID()),
render_widget_id_(source.GetRoutingID()),
- delivery_log_(),
capture_callback_(capture_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -453,15 +422,14 @@ ContentCaptureSubscription::ContentCaptureSubscription(
#endif
refresh_subscriber_.reset(new FrameSubscriber(
media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy,
- &delivery_log_,
cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
: base::WeakPtr<CursorRenderer>(),
window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
: base::WeakPtr<WindowActivityTracker>()));
mouse_activity_subscriber_.reset(new FrameSubscriber(
media::VideoCaptureOracle::kMouseCursorUpdate, oracle_proxy,
- &delivery_log_, cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
- : base::WeakPtr<CursorRenderer>(),
+ cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
+ : base::WeakPtr<CursorRenderer>(),
window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
: base::WeakPtr<WindowActivityTracker>()));
@@ -471,8 +439,8 @@ ContentCaptureSubscription::ContentCaptureSubscription(
std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
new FrameSubscriber(
media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy,
- &delivery_log_, cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
- : base::WeakPtr<CursorRenderer>(),
+ cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
+ : base::WeakPtr<CursorRenderer>(),
window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
: base::WeakPtr<WindowActivityTracker>()));
view->BeginFrameSubscription(std::move(subscriber));
@@ -595,31 +563,6 @@ void RenderVideoFrame(
done_cb.Run(region_in_frame, true);
}
-VideoFrameDeliveryLog::VideoFrameDeliveryLog()
- : last_frame_rate_log_time_(), count_frames_rendered_(0) {}
-
-void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
- // Log frame rate, if verbose logging is turned on.
- static const base::TimeDelta kFrameRateLogInterval =
- base::TimeDelta::FromSeconds(10);
- if (last_frame_rate_log_time_.is_null()) {
- last_frame_rate_log_time_ = frame_time;
- count_frames_rendered_ = 0;
- } else {
- ++count_frames_rendered_;
- const base::TimeDelta elapsed = frame_time - last_frame_rate_log_time_;
- if (elapsed >= kFrameRateLogInterval) {
- const double measured_fps = count_frames_rendered_ / elapsed.InSecondsF();
- UMA_HISTOGRAM_COUNTS("TabCapture.FrameRate",
- static_cast<int>(measured_fps));
- VLOG(1) << "Current measured frame rate for "
- << "WebContentsVideoCaptureDevice is " << measured_fps << " FPS.";
- last_frame_rate_log_time_ = frame_time;
- count_frames_rendered_ = 0;
- }
- }
-}
-
WebContentsCaptureMachine::WebContentsCaptureMachine(
int render_process_id,
int main_render_frame_id,
@@ -779,15 +722,7 @@ void WebContentsCaptureMachine::Capture(
return;
}
- gfx::Size view_size = view->GetViewBounds().size();
- if (view_size != last_view_size_) {
- last_view_size_ = view_size;
-
- // Measure the number of kilopixels.
- UMA_HISTOGRAM_COUNTS_10000("TabCapture.ViewChangeKiloPixels",
- view_size.width() * view_size.height() / 1024);
- }
-
+ const gfx::Size view_size = view->GetViewBounds().size();
if (view->CanCopyToVideoFrame()) {
view->CopyFromCompositingSurfaceToVideoFrame(
gfx::Rect(view_size), target,
@@ -886,10 +821,8 @@ void WebContentsCaptureMachine::DidCopyFromBackingStore(
ReadbackResponse response) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::TimeTicks now = base::TimeTicks::Now();
DCHECK(render_thread_);
if (response == READBACK_SUCCESS) {
- UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", target.get(),
"Render");
render_thread_->task_runner()->PostTask(
@@ -910,14 +843,9 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& region_in_frame,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::TimeTicks now = base::TimeTicks::Now();
- if (success) {
- UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time);
- } else {
- // Capture can fail due to transient issues, so just skip this frame.
- DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
- }
+ // Capture can fail due to transient issues, so just skip this frame.
+ DVLOG_IF(1, !success) << "CopyFromCompositingSurface failed; skipping frame.";
deliver_frame_cb.Run(start_time, region_in_frame, success);
}
@@ -992,19 +920,18 @@ WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
}
// static
-media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
- const std::string& device_id) {
+std::unique_ptr<media::VideoCaptureDevice>
+WebContentsVideoCaptureDevice::Create(const std::string& device_id) {
// Parse device_id into render_process_id and main_render_frame_id.
- int render_process_id = -1;
- int main_render_frame_id = -1;
- if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget(
- device_id, &render_process_id, &main_render_frame_id)) {
+ WebContentsMediaCaptureId media_id;
+ if (!WebContentsMediaCaptureId::Parse(device_id, &media_id)) {
return NULL;
}
- return new WebContentsVideoCaptureDevice(
- render_process_id, main_render_frame_id,
- WebContentsMediaCaptureId::IsAutoThrottlingOptionSet(device_id));
+ return std::unique_ptr<media::VideoCaptureDevice>(
+ new WebContentsVideoCaptureDevice(media_id.render_process_id,
+ media_id.main_render_frame_id,
+ media_id.enable_auto_throttling));
}
void WebContentsVideoCaptureDevice::AllocateAndStart(
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.h b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
index 6bcddfa98dd..6063f7e1fb3 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.h
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
@@ -30,7 +30,8 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice
public:
// Create a WebContentsVideoCaptureDevice instance from the given
// |device_id|. Returns NULL if |device_id| is invalid.
- static media::VideoCaptureDevice* Create(const std::string& device_id);
+ static std::unique_ptr<media::VideoCaptureDevice> Create(
+ const std::string& device_id);
~WebContentsVideoCaptureDevice() override;
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 922ce7c835d..ffdfc173eb5 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
@@ -33,11 +33,11 @@
#include "content/test/test_render_frame_host_factory.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
-#include "media/base/video_capture_types.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
#include "media/capture/video/video_capture_buffer_pool_impl.h"
+#include "media/capture/video_capture_types.h"
#include "skia/ext/platform_canvas.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -375,7 +375,7 @@ class StubClient : public media::VideoCaptureDevice::Client {
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override {
+ scoped_refptr<media::VideoFrame> frame) override {
EXPECT_FALSE(frame->visible_rect().IsEmpty());
EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format());
double frame_rate = 0;
@@ -442,12 +442,17 @@ class StubClient : public media::VideoCaptureDevice::Client {
return buffer_handle_->mapped_size();
}
void* data(int plane) override { return buffer_handle_->data(plane); }
- ClientBuffer AsClientBuffer(int plane) override { return nullptr; }
#if defined(OS_POSIX) && !defined(OS_MACOSX)
base::FileDescriptor AsPlatformFile() override {
return base::FileDescriptor();
}
#endif
+ bool IsBackedByVideoFrame() const override {
+ return buffer_handle_->IsBackedByVideoFrame();
+ }
+ scoped_refptr<media::VideoFrame> GetVideoFrame() override {
+ return buffer_handle_->GetVideoFrame();
+ }
private:
~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); }
@@ -598,10 +603,14 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
protected:
void SetUp() override {
- test_screen_.display()->set_id(0x1337);
- test_screen_.display()->set_bounds(gfx::Rect(0, 0, 2560, 1440));
- test_screen_.display()->set_device_scale_factor(kTestDeviceScaleFactor);
-
+ const display::Display test_display = test_screen_.GetPrimaryDisplay();
+ display::Display display(test_display);
+ display.set_id(0x1337);
+ display.set_bounds(gfx::Rect(0, 0, 2560, 1440));
+ display.set_device_scale_factor(kTestDeviceScaleFactor);
+ test_screen_.display_list().RemoveDisplay(test_display.id());
+ test_screen_.display_list().AddDisplay(display,
+ display::DisplayList::Type::PRIMARY);
display::Screen::SetScreenInstance(&test_screen_);
ASSERT_EQ(&test_screen_, display::Screen::GetScreen());
@@ -629,10 +638,9 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
web_contents_.reset(
TestWebContents::Create(browser_context_.get(), site_instance.get()));
RenderFrameHost* const main_frame = web_contents_->GetMainFrame();
- device_.reset(WebContentsVideoCaptureDevice::Create(
- base::StringPrintf("web-contents-media-stream://%d:%d",
- main_frame->GetProcess()->GetID(),
- main_frame->GetRoutingID())));
+ device_ = WebContentsVideoCaptureDevice::Create(base::StringPrintf(
+ "web-contents-media-stream://%d:%d", main_frame->GetProcess()->GetID(),
+ main_frame->GetRoutingID()));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 456d5e21386..066b81111c6 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -10,33 +10,35 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "media/base/media.h"
+#include "media/base/media_switches.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
-#include "media/base/media.h"
-#include "media/base/media_switches.h"
#endif
-#if defined(ENABLE_MOJO_RENDERER)
-// TODO(xhwang): Enable tests by running AesDecryptor in remote mojo CDM and
-// using ExternalClearKey instead of ClearKey: crbug.com/641559
-#define DISABLE_ENCRYPTED_MEDIA_PLAYBACK_TESTS 1
+#if defined(ENABLE_MOJO_CDM)
+// 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.
+// Note that External Clear Key is also supported in chrome/ when pepper CDM is
+// used, which is tested in browser_tests.
+#define SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL
#endif
// Available key systems.
const char kClearKeyKeySystem[] = "org.w3.clearkey";
-#if defined(OS_ANDROID)
+#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
#endif
// Supported media types.
const char kWebMVorbisAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
-#if !defined(DISABLE_ENCRYPTED_MEDIA_PLAYBACK_TESTS)
const char kWebMOpusAudioOnly[] = "audio/webm; codecs=\"opus\"";
const char kWebMVP8VideoOnly[] = "video/webm; codecs=\"vp8\"";
+const char kWebMVP9VideoOnly[] = "video/webm; codecs=\"vp9\"";
const char kWebMOpusAudioVP9Video[] = "video/webm; codecs=\"opus, vp9\"";
-#endif
const char kWebMVorbisAudioVP8Video[] = "video/webm; codecs=\"vorbis, vp8\"";
// EME-specific test results and errors.
@@ -129,7 +131,7 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(
switches::kDisableGestureRequirementForMediaPlayback);
-#if defined(OS_ANDROID)
+#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
command_line->AppendSwitchASCII(switches::kEnableFeatures,
media::kExternalClearKeyForTesting.name);
#endif
@@ -145,7 +147,18 @@ INSTANTIATE_TEST_CASE_P(SRC_ClearKey, EncryptedMediaTest,
INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
Combine(Values(kClearKeyKeySystem), Values(MSE)));
-#if !defined(DISABLE_ENCRYPTED_MEDIA_PLAYBACK_TESTS)
+#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
+INSTANTIATE_TEST_CASE_P(SRC_ExternalClearKey,
+ EncryptedMediaTest,
+ Combine(Values(kExternalClearKeyKeySystem),
+ Values(SRC)));
+
+INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKey,
+ EncryptedMediaTest,
+ Combine(Values(kExternalClearKeyKeySystem),
+ Values(MSE)));
+#endif
+
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
TestSimplePlayback("bear-a_enc-a.webm", kWebMVorbisAudioOnly);
}
@@ -162,6 +175,16 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
TestSimplePlayback("bear-320x240-v_enc-v.webm", kWebMVP8VideoOnly);
}
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_Fullsample) {
+ TestSimplePlayback("bear-320x240-v-vp9_fullsample_enc-v.webm",
+ kWebMVP9VideoOnly);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_Subsample) {
+ TestSimplePlayback("bear-320x240-v-vp9_subsample_enc-v.webm",
+ kWebMVP9VideoOnly);
+}
+
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
TestSimplePlayback("bear-320x240-av_enc-v.webm", kWebMVorbisAudioVP8Video);
}
@@ -198,7 +221,6 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
TestFrameSizeChange();
}
-#endif // !defined(DISABLE_ENCRYPTED_MEDIA_PLAYBACK_TESTS)
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
@@ -206,16 +228,4 @@ IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
kEmeNotSupportedError);
}
-#if defined(OS_ANDROID)
-// On Android, External Clear Key is supported in //content/shell/ by using mojo
-// CDM with AesDecryptor running in the GPU process.
-// On other platforms, External Clear Key is supported in chrome/, so it is
-// tested in browser_tests.
-IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, ExternalClearKeyPlayback) {
- RunSimpleEncryptedMediaTest("bear-320x240-av_enc-av.webm",
- kWebMVorbisAudioVP8Video,
- kExternalClearKeyKeySystem, MSE);
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 633b562b883..d2e83ce3fd8 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -220,13 +220,12 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBear3gpAmrnbMpeg4) {
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavGsmms) {
PlayAudio("bear_gsm_ms.wav", GetParam());
}
-
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearFlac) {
- PlayAudio("bear.flac", GetParam());
-}
#endif // defined(USE_PROPRIETARY_CODECS)
#endif // defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearFlac) {
+ PlayAudio("bear.flac", GetParam());
+}
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavAlaw) {
PlayAudio("bear_alaw.wav", GetParam());
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index 79ab549107a..1ae324db123 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -210,6 +210,12 @@ 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\"'"));
@@ -362,6 +368,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
@@ -427,6 +434,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
@@ -491,6 +499,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
@@ -611,6 +620,34 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
TestOGGUnacceptableCombinations("application/ogg");
}
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_flac) {
+ EXPECT_EQ(kProbably, CanPlay("'audio/flac'"));
+
+ // Only audio/flac is supported.
+ 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\"'"));
+
+ // Currently only flac in a flac container is supported.
+ 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\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc3.64001F\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.40.02\"'"));
+}
+
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'video/mp3'"));
EXPECT_EQ(kNot, CanPlay("'video/mpeg'"));
@@ -765,6 +802,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.01.08.02.01.01.00\"'"));
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\"'"));
@@ -876,6 +914,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kAc3Eac3Probably, 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\"'"));
diff --git a/chromium/content/browser/media/media_devices_permission_checker.cc b/chromium/content/browser/media/media_devices_permission_checker.cc
new file mode 100644
index 00000000000..d18a0a0a42c
--- /dev/null
+++ b/chromium/content/browser/media/media_devices_permission_checker.cc
@@ -0,0 +1,153 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/media_devices_permission_checker.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/common/media/media_devices.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_switches.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+MediaDevicesManager::BoolDeviceTypes DoCheckPermissionsOnUIThread(
+ MediaDevicesManager::BoolDeviceTypes requested_device_types,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* frame_host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+
+ // If there is no |frame_host|, return false for all permissions.
+ if (!frame_host)
+ return MediaDevicesManager::BoolDeviceTypes();
+
+ RenderFrameHostDelegate* delegate = frame_host->delegate();
+ GURL origin = security_origin.GetURL();
+
+ // Currently, the MEDIA_DEVICE_AUDIO_CAPTURE permission is used for
+ // both audio input and output.
+ // TODO(guidou): use specific permission for audio output when it becomes
+ // available. See http://crbug.com/556542.
+ bool has_audio_permission =
+ (requested_device_types[MEDIA_DEVICE_TYPE_AUDIO_INPUT] ||
+ requested_device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) &&
+ delegate->CheckMediaAccessPermission(origin, MEDIA_DEVICE_AUDIO_CAPTURE);
+
+ MediaDevicesManager::BoolDeviceTypes result;
+ result[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = has_audio_permission;
+ result[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = has_audio_permission;
+ result[MEDIA_DEVICE_TYPE_VIDEO_INPUT] =
+ requested_device_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT] &&
+ delegate->CheckMediaAccessPermission(origin, MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ return result;
+}
+
+bool CheckSinglePermissionOnUIThread(MediaDeviceType device_type,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ MediaDevicesManager::BoolDeviceTypes requested;
+ requested[device_type] = true;
+ MediaDevicesManager::BoolDeviceTypes result = DoCheckPermissionsOnUIThread(
+ requested, render_process_id, render_frame_id, security_origin);
+ return result[device_type];
+}
+
+} // namespace
+
+MediaDevicesPermissionChecker::MediaDevicesPermissionChecker()
+ : use_override_(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeUIForMediaStream)),
+ override_value_(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kUseFakeUIForMediaStream) != "deny") {}
+
+MediaDevicesPermissionChecker::MediaDevicesPermissionChecker(
+ bool override_value)
+ : use_override_(true), override_value_(override_value) {}
+
+bool MediaDevicesPermissionChecker::CheckPermissionOnUIThread(
+ MediaDeviceType device_type,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) const {
+ if (use_override_)
+ return override_value_;
+
+ return CheckSinglePermissionOnUIThread(device_type, render_process_id,
+ render_frame_id, security_origin);
+}
+
+void MediaDevicesPermissionChecker::CheckPermission(
+ MediaDeviceType device_type,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin,
+ const base::Callback<void(bool)>& callback) const {
+ if (use_override_) {
+ callback.Run(override_value_);
+ return;
+ }
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CheckSinglePermissionOnUIThread, device_type,
+ render_process_id, render_frame_id, security_origin),
+ callback);
+}
+
+MediaDevicesManager::BoolDeviceTypes
+MediaDevicesPermissionChecker::CheckPermissionsOnUIThread(
+ MediaDevicesManager::BoolDeviceTypes requested_device_types,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) const {
+ if (use_override_) {
+ MediaDevicesManager::BoolDeviceTypes result;
+ result.fill(override_value_);
+ return result;
+ }
+
+ return DoCheckPermissionsOnUIThread(requested_device_types, render_process_id,
+ render_frame_id, security_origin);
+}
+
+void MediaDevicesPermissionChecker::CheckPermissions(
+ MediaDevicesManager::BoolDeviceTypes requested,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin,
+ const base::Callback<void(const MediaDevicesManager::BoolDeviceTypes&)>&
+ callback) const {
+ if (use_override_) {
+ MediaDevicesManager::BoolDeviceTypes result;
+ result.fill(override_value_);
+ callback.Run(result);
+ return;
+ }
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DoCheckPermissionsOnUIThread, requested, render_process_id,
+ render_frame_id, security_origin),
+ callback);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/media_devices_permission_checker.h b/chromium/content/browser/media/media_devices_permission_checker.h
new file mode 100644
index 00000000000..43b175b0ad3
--- /dev/null
+++ b/chromium/content/browser/media/media_devices_permission_checker.h
@@ -0,0 +1,92 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_MEDIA_DEVICES_PERMISSION_CHECKER_H_
+#define CONTENT_BROWSER_MEDIA_MEDIA_DEVICES_PERMISSION_CHECKER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/browser/renderer_host/media/media_devices_manager.h"
+#include "content/common/content_export.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+// This class provides various utility functions to check if a render frame
+// has permission to access media devices. Note that none of the methods
+// prompts the user to request permission.
+class CONTENT_EXPORT MediaDevicesPermissionChecker {
+ public:
+ MediaDevicesPermissionChecker();
+ // This constructor creates a MediaDevicesPermissionChecker that replies
+ // |override_value| to all permission requests. Use only for testing.
+ explicit MediaDevicesPermissionChecker(bool override_value);
+
+ // Checks if the origin |security_origin| associated to a render frame
+ // identified by |render_process_id| and |render_frame_id| is allowed to
+ // access the media device type |device_type|.
+ // This method must be called on the UI thread.
+ bool CheckPermissionOnUIThread(MediaDeviceType device_type,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) const;
+
+ // Checks if the origin |security_origin| associated to a render frame
+ // identified by |render_process_id| and |render_frame_id| is allowed to
+ // access the media device type |device_type|. The result is passed to
+ // |callback|.
+ // This method can be called on any thread. |callback| is fired on the same
+ // thread this method is called on.
+ void CheckPermission(MediaDeviceType device_type,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin,
+ const base::Callback<void(bool)>& callback) const;
+
+ // Checks if the origin |security_origin| associated to a render frame
+ // identified by |render_process_id| and |render_frame_id| is allowed to
+ // access the media device types marked with a value of true in
+ // |requested_device_types|. The result is indexed by MediaDeviceType.
+ // Entries in the result with a value of true for requested device types
+ // indicate that the frame has permission to access devices of the
+ // corresponding types.
+ // This method must be called on the UI thread.
+ MediaDevicesManager::BoolDeviceTypes CheckPermissionsOnUIThread(
+ MediaDevicesManager::BoolDeviceTypes requested_device_types,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin) const;
+
+ // Checks if the origin |security_origin| associated to a render frame
+ // identified by |render_process_id| and |render_frame_id| is allowed to
+ // access the media device types marked with a value of true in
+ // |requested_device_types|. The result is passed to |callback|. The result is
+ // indexed by MediaDeviceType. Entries in the result with a value of true for
+ // requested device types indicate that the frame has permission to access
+ // devices of the corresponding types.
+ // This method can be called on any thread. |callback| is fired on the same
+ // thread this method is called on.
+ void CheckPermissions(
+ MediaDevicesManager::BoolDeviceTypes requested_device_types,
+ int render_process_id,
+ int render_frame_id,
+ const url::Origin& security_origin,
+ const base::Callback<void(const MediaDevicesManager::BoolDeviceTypes&)>&
+ callback) const;
+
+ private:
+ const bool use_override_;
+ const bool override_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaDevicesPermissionChecker);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_MEDIA_DEVICES_PERMISSION_CHECKER_H_
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index e53a547fcaf..9eb8da07804 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -335,7 +335,8 @@ class MediaInternals::MediaInternalsUMAHandler {
}
enum class FinalizeType { EVERYTHING, POWER_ONLY };
- void FinalizeWatchTime(WatchTimeInfo* watch_time_info,
+ void FinalizeWatchTime(bool has_video,
+ WatchTimeInfo* watch_time_info,
FinalizeType finalize_type) {
// Use a macro instead of a function so we can use the histogram macro (which
// checks that the uma name is a static value). We use a custom time range for
@@ -348,16 +349,29 @@ class MediaInternals::MediaInternalsUMAHandler {
watch_time_info->watch_time = media::kNoTimestamp; \
}
- if (finalize_type == FinalizeType::EVERYTHING) {
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAll, all_watch_time);
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoMse, mse_watch_time);
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoEme, eme_watch_time);
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoSrc, src_watch_time);
+ if (has_video) {
+ if (finalize_type == FinalizeType::EVERYTHING) {
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAll, all_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoMse, mse_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoEme, eme_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoSrc, src_watch_time);
+ } else {
+ DCHECK_EQ(finalize_type, FinalizeType::POWER_ONLY);
+ }
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoBattery, battery_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAc, ac_watch_time);
} else {
- DCHECK_EQ(finalize_type, FinalizeType::POWER_ONLY);
+ if (finalize_type == FinalizeType::EVERYTHING) {
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioAll, all_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioMse, mse_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioEme, eme_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioSrc, src_watch_time);
+ } else {
+ DCHECK_EQ(finalize_type, FinalizeType::POWER_ONLY);
+ }
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioBattery, battery_watch_time);
+ MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioAc, ac_watch_time);
}
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoBattery, battery_watch_time);
- MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAc, ac_watch_time);
#undef MAYBE_RECORD_WATCH_TIME
}
@@ -425,7 +439,23 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
break;
case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: {
DVLOG(2) << "Processing watch time update.";
- WatchTimeInfo& wti = player_info[event.id].watch_time_info;
+ PipelineInfo& info = player_info[event.id];
+ WatchTimeInfo& wti = info.watch_time_info;
+ // Save audio only watch time information.
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioAll,
+ &wti.all_watch_time);
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioMse,
+ &wti.mse_watch_time);
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioEme,
+ &wti.eme_watch_time);
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioSrc,
+ &wti.src_watch_time);
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioBattery,
+ &wti.battery_watch_time);
+ MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioAc,
+ &wti.ac_watch_time);
+
+ // Save audio+video watch time information.
MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoAll,
&wti.all_watch_time);
MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoMse,
@@ -444,14 +474,14 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalize,
&should_finalize) &&
should_finalize);
- FinalizeWatchTime(&wti, FinalizeType::EVERYTHING);
+ FinalizeWatchTime(info.has_video, &wti, FinalizeType::EVERYTHING);
} else if (event.params.HasKey(
media::MediaLog::kWatchTimeFinalizePower)) {
bool should_finalize;
DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalizePower,
&should_finalize) &&
should_finalize);
- FinalizeWatchTime(&wti, FinalizeType::POWER_ONLY);
+ FinalizeWatchTime(info.has_video, &wti, FinalizeType::POWER_ONLY);
}
break;
}
@@ -554,7 +584,8 @@ void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
auto it = players_it->second.begin();
while (it != players_it->second.end()) {
ReportUMAForPipelineStatus(it->second);
- FinalizeWatchTime(&(it->second.watch_time_info), FinalizeType::EVERYTHING);
+ FinalizeWatchTime(it->second.has_video, &(it->second.watch_time_info),
+ FinalizeType::EVERYTHING);
players_it->second.erase(it++);
}
renderer_info_.erase(players_it);
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 9a785538822..94e60d8a5f2 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -23,11 +23,10 @@
#include "content/public/browser/notification_registrar.h"
#include "media/audio/audio_logging.h"
#include "media/base/media_log.h"
-#include "media/base/video_capture_types.h"
#include "media/capture/video/video_capture_device_descriptor.h"
+#include "media/capture/video_capture_types.h"
namespace media {
-class AudioParameters;
struct MediaLogEvent;
}
diff --git a/chromium/content/browser/media/media_redirect_browsertest.cc b/chromium/content/browser/media/media_redirect_browsertest.cc
index 0d809e69f0e..cc8a0294951 100644
--- a/chromium/content/browser/media/media_redirect_browsertest.cc
+++ b/chromium/content/browser/media/media_redirect_browsertest.cc
@@ -21,7 +21,7 @@ class MediaRedirectTest : public MediaBrowserTest {
std::unique_ptr<net::EmbeddedTestServer> http_test_server(
new net::EmbeddedTestServer());
http_test_server->ServeFilesFromSourceDirectory(media::GetTestDataPath());
- CHECK(http_test_server->Start());
+ CHECK(http_test_server->InitializeAndListen());
const GURL player_url =
http_test_server->GetURL("/player.html?video=" + kHiddenPath);
@@ -30,6 +30,7 @@ class MediaRedirectTest : public MediaBrowserTest {
http_test_server->RegisterRequestHandler(
base::Bind(&MediaRedirectTest::RedirectResponseHandler,
base::Unretained(this), dest_url));
+ http_test_server->StartAcceptingConnections();
// Run the normal media playback test.
EXPECT_EQ(kEnded, RunTest(player_url, kEnded));
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index ef3f5dc9c9d..a1fe8da2bcf 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -43,9 +43,6 @@ void MediaWebContentsObserver::RenderFrameDeleted(
}
void MediaWebContentsObserver::MaybeUpdateAudibleState() {
- if (!AudioStreamMonitor::monitoring_available())
- return;
-
AudioStreamMonitor* audio_stream_monitor =
static_cast<WebContentsImpl*>(web_contents())->audio_stream_monitor();
@@ -109,7 +106,8 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
if (removed_audio || removed_video) {
// Notify observers the player has been "paused".
static_cast<WebContentsImpl*>(web_contents())
- ->MediaStoppedPlaying(player_id);
+ ->MediaStoppedPlaying(
+ WebContentsObserver::MediaPlayerInfo(removed_video), player_id);
}
if (reached_end_of_stream)
@@ -132,17 +130,9 @@ void MediaWebContentsObserver::OnMediaPlaying(
return;
const MediaPlayerId id(render_frame_host, delegate_id);
- if (has_audio) {
+ if (has_audio)
AddMediaPlayerEntry(id, &active_audio_players_);
- // If we don't have audio stream monitoring, allocate the audio power save
- // blocker here instead of during NotifyNavigationStateChanged().
- if (!audio_power_save_blocker_ &&
- !AudioStreamMonitor::monitoring_available()) {
- CreateAudioPowerSaveBlocker();
- }
- }
-
if (has_video) {
AddMediaPlayerEntry(id, &active_video_players_);
@@ -160,22 +150,29 @@ void MediaWebContentsObserver::OnMediaPlaying(
// Notify observers of the new player.
DCHECK(has_audio || has_video);
- static_cast<WebContentsImpl*>(web_contents())->MediaStartedPlaying(id);
+ static_cast<WebContentsImpl*>(web_contents())
+ ->MediaStartedPlaying(WebContentsObserver::MediaPlayerInfo(has_video),
+ id);
}
void MediaWebContentsObserver::ClearPowerSaveBlockers(
RenderFrameHost* render_frame_host) {
std::set<MediaPlayerId> removed_players;
- RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_,
- &removed_players);
RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_,
&removed_players);
+ std::set<MediaPlayerId> video_players(removed_players);
+ RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_,
+ &removed_players);
MaybeReleasePowerSaveBlockers();
// Notify all observers the player has been "paused".
WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
- for (const auto& id : removed_players)
- wci->MediaStoppedPlaying(id);
+ for (const auto& id : removed_players) {
+ auto it = video_players.find(id);
+ bool was_video = (it != video_players.end());
+ wci->MediaStoppedPlaying(WebContentsObserver::MediaPlayerInfo(was_video),
+ id);
+ }
}
void MediaWebContentsObserver::CreateAudioPowerSaveBlocker() {
@@ -204,14 +201,6 @@ void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() {
}
void MediaWebContentsObserver::MaybeReleasePowerSaveBlockers() {
- // If there are no more audio players and we don't have audio stream
- // monitoring, release the audio power save blocker here instead of during
- // NotifyNavigationStateChanged().
- if (active_audio_players_.empty() &&
- !AudioStreamMonitor::monitoring_available()) {
- audio_power_save_blocker_.reset();
- }
-
// If there are no more video players, clear the video power save blocker.
if (active_video_players_.empty())
video_power_save_blocker_.reset();
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 5d6d8d2f5ff..6b845a3132f 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -11,6 +11,7 @@
#include <memory>
#include <set>
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
#include "content/browser/media/session/media_session_controllers_manager.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/media/midi_host.cc b/chromium/content/browser/media/midi_host.cc
index 17dccccfea5..ed01c71f4ac 100644
--- a/chromium/content/browser/media/midi_host.cc
+++ b/chromium/content/browser/media/midi_host.cc
@@ -6,20 +6,17 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/media/media_internals.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/media_observer.h"
#include "content/public/browser/user_metrics.h"
+#include "media/midi/message_util.h"
#include "media/midi/midi_manager.h"
#include "media/midi/midi_message_queue.h"
-#include "media/midi/midi_message_util.h"
namespace content {
namespace {
@@ -34,21 +31,19 @@ const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB.
// how many bytes will be sent before reporting back to the renderer.
const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB.
-bool IsDataByte(uint8_t data) {
- return (data & 0x80) == 0;
-}
-
-bool IsSystemRealTimeMessage(uint8_t data) {
- return 0xf8 <= data && data <= 0xff;
-}
-
} // namespace
-using media::midi::kSysExByte;
-using media::midi::kEndOfSysExByte;
+using midi::IsDataByte;
+using midi::IsSystemRealTimeMessage;
+using midi::IsValidWebMIDIData;
+using midi::MidiPortInfo;
+using midi::kSysExByte;
+using midi::kEndOfSysExByte;
+using midi::mojom::PortState;
+using midi::mojom::Result;
MidiHost::MidiHost(int renderer_process_id,
- media::midi::MidiManager* midi_manager)
+ midi::MidiManager* midi_manager)
: BrowserMessageFilter(MidiMsgStart),
renderer_process_id_(renderer_process_id),
has_sys_ex_permission_(false),
@@ -143,9 +138,9 @@ void MidiHost::OnEndSession() {
midi_manager_->EndSession(this);
}
-void MidiHost::CompleteStartSession(media::midi::Result result) {
+void MidiHost::CompleteStartSession(Result result) {
DCHECK(is_session_requested_);
- if (result == media::midi::Result::OK) {
+ if (result == Result::OK) {
// ChildSecurityPolicy is set just before OnStartSession by
// MidiDispatcherHost. So we can safely cache the policy.
has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()->
@@ -154,26 +149,24 @@ void MidiHost::CompleteStartSession(media::midi::Result result) {
Send(new MidiMsg_SessionStarted(result));
}
-void MidiHost::AddInputPort(const media::midi::MidiPortInfo& info) {
+void MidiHost::AddInputPort(const MidiPortInfo& info) {
base::AutoLock auto_lock(messages_queues_lock_);
// MidiMessageQueue is created later in ReceiveMidiData().
received_messages_queues_.push_back(nullptr);
Send(new MidiMsg_AddInputPort(info));
}
-void MidiHost::AddOutputPort(const media::midi::MidiPortInfo& info) {
+void MidiHost::AddOutputPort(const MidiPortInfo& info) {
base::AutoLock auto_lock(output_port_count_lock_);
output_port_count_++;
Send(new MidiMsg_AddOutputPort(info));
}
-void MidiHost::SetInputPortState(uint32_t port,
- media::midi::MidiPortState state) {
+void MidiHost::SetInputPortState(uint32_t port, PortState state) {
Send(new MidiMsg_SetInputPortState(port, state));
}
-void MidiHost::SetOutputPortState(uint32_t port,
- media::midi::MidiPortState state) {
+void MidiHost::SetOutputPortState(uint32_t port, PortState state) {
Send(new MidiMsg_SetOutputPortState(port, state));
}
@@ -189,7 +182,7 @@ void MidiHost::ReceiveMidiData(uint32_t port,
// Lazy initialization
if (received_messages_queues_[port] == nullptr)
- received_messages_queues_[port] = new media::midi::MidiMessageQueue(true);
+ received_messages_queues_[port] = new midi::MidiMessageQueue(true);
received_messages_queues_[port]->Add(data, length);
std::vector<uint8_t> message;
@@ -232,42 +225,4 @@ void MidiHost::Detach() {
midi_manager_ = nullptr;
}
-// static
-bool MidiHost::IsValidWebMIDIData(const std::vector<uint8_t>& data) {
- bool in_sysex = false;
- size_t sysex_start_offset = 0;
- size_t waiting_data_length = 0;
- for (size_t i = 0; i < data.size(); ++i) {
- const uint8_t current = data[i];
- if (IsSystemRealTimeMessage(current))
- continue; // Real time message can be placed at any point.
- if (waiting_data_length > 0) {
- if (!IsDataByte(current))
- return false; // Error: |current| should have been data byte.
- --waiting_data_length;
- continue; // Found data byte as expected.
- }
- if (in_sysex) {
- if (data[i] == kEndOfSysExByte) {
- in_sysex = false;
- UMA_HISTOGRAM_COUNTS("Media.Midi.SysExMessageSizeUpTo1MB",
- i - sysex_start_offset + 1);
- } else if (!IsDataByte(current)) {
- return false; // Error: |current| should have been data byte.
- }
- continue; // Found data byte as expected.
- }
- if (current == kSysExByte) {
- in_sysex = true;
- sysex_start_offset = i;
- continue; // Found SysEX
- }
- waiting_data_length = media::midi::GetMidiMessageLength(current);
- if (waiting_data_length == 0)
- return false; // Error: |current| should have been a valid status byte.
- --waiting_data_length; // Found status byte
- }
- return waiting_data_length == 0 && !in_sysex;
-}
-
} // namespace content
diff --git a/chromium/content/browser/media/midi_host.h b/chromium/content/browser/media/midi_host.h
index fc126acd357..95e69031f23 100644
--- a/chromium/content/browser/media/midi_host.h
+++ b/chromium/content/browser/media/midi_host.h
@@ -21,21 +21,20 @@
#include "content/public/browser/browser_thread.h"
#include "media/midi/midi_manager.h"
#include "media/midi/midi_port_info.h"
+#include "media/midi/midi_service.mojom.h"
-namespace media {
namespace midi {
class MidiManager;
class MidiMessageQueue;
-}
-}
+} // namespace midi
namespace content {
class CONTENT_EXPORT MidiHost : public BrowserMessageFilter,
- public media::midi::MidiManagerClient {
+ public midi::MidiManagerClient {
public:
// Called from UI thread from the owner of this object.
- MidiHost(int renderer_process_id, media::midi::MidiManager* midi_manager);
+ MidiHost(int renderer_process_id, midi::MidiManager* midi_manager);
// BrowserMessageFilter implementation.
void OnChannelClosing() override;
@@ -43,13 +42,11 @@ class CONTENT_EXPORT MidiHost : public BrowserMessageFilter,
bool OnMessageReceived(const IPC::Message& message) override;
// MidiManagerClient implementation.
- void CompleteStartSession(media::midi::Result result) override;
- void AddInputPort(const media::midi::MidiPortInfo& info) override;
- void AddOutputPort(const media::midi::MidiPortInfo& info) override;
- void SetInputPortState(uint32_t port,
- media::midi::MidiPortState state) override;
- void SetOutputPortState(uint32_t port,
- media::midi::MidiPortState state) override;
+ void CompleteStartSession(midi::mojom::Result result) override;
+ void AddInputPort(const midi::MidiPortInfo& info) override;
+ void AddOutputPort(const midi::MidiPortInfo& info) override;
+ void SetInputPortState(uint32_t port, midi::mojom::PortState state) override;
+ void SetOutputPortState(uint32_t port, midi::mojom::PortState state) override;
void ReceiveMidiData(uint32_t port,
const uint8_t* data,
size_t length,
@@ -71,17 +68,9 @@ class CONTENT_EXPORT MidiHost : public BrowserMessageFilter,
~MidiHost() override;
private:
- FRIEND_TEST_ALL_PREFIXES(MidiHostTest, IsValidWebMIDIData);
friend class base::DeleteHelper<MidiHost>;
friend class BrowserThread;
- // Returns true if |data| fulfills the requirements of MidiOutput.send API
- // defined in the Web MIDI spec.
- // - |data| must be any number of complete MIDI messages (data abbreviation
- // called "running status" is disallowed).
- // - 1-byte MIDI realtime messages can be placed at any position of |data|.
- static bool IsValidWebMIDIData(const std::vector<uint8_t>& data);
-
int renderer_process_id_;
// Represents if the renderer has a permission to send/receive MIDI SysEX
@@ -96,10 +85,10 @@ class CONTENT_EXPORT MidiHost : public BrowserMessageFilter,
// does not support MIDI. If not supported then a call to
// OnRequestAccess() will always refuse access and a call to
// OnSendData() will do nothing.
- media::midi::MidiManager* midi_manager_;
+ midi::MidiManager* midi_manager_;
// Buffers where data sent from each MIDI input port is stored.
- ScopedVector<media::midi::MidiMessageQueue> received_messages_queues_;
+ ScopedVector<midi::MidiMessageQueue> received_messages_queues_;
// Protects access to |received_messages_queues_|;
base::Lock messages_queues_lock_;
diff --git a/chromium/content/browser/media/midi_host_unittest.cc b/chromium/content/browser/media/midi_host_unittest.cc
index 21306af09a1..866d4469be7 100644
--- a/chromium/content/browser/media/midi_host_unittest.cc
+++ b/chromium/content/browser/media/midi_host_unittest.cc
@@ -19,38 +19,11 @@
namespace content {
namespace {
-const uint8_t kGMOn[] = {0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7};
-const uint8_t kGSOn[] = {
- 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7,
-};
-const uint8_t kNoteOn[] = {0x90, 0x3c, 0x7f};
-const uint8_t kNoteOnWithRunningStatus[] = {
- 0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f,
-};
-const uint8_t kChannelPressure[] = {0xd0, 0x01};
-const uint8_t kChannelPressureWithRunningStatus[] = {
- 0xd0, 0x01, 0x01, 0x01,
-};
-const uint8_t kTimingClock[] = {0xf8};
-const uint8_t kBrokenData1[] = {0x90};
-const uint8_t kBrokenData2[] = {0xf7};
-const uint8_t kBrokenData3[] = {0xf2, 0x00};
-const uint8_t kDataByte0[] = {0x00};
+using midi::mojom::PortState;
+const uint8_t kNoteOn[] = {0x90, 0x3c, 0x7f};
const int kRenderProcessId = 0;
-template <typename T, size_t N>
-const std::vector<T> AsVector(const T(&data)[N]) {
- std::vector<T> buffer;
- buffer.insert(buffer.end(), data, data + N);
- return buffer;
-}
-
-template <typename T, size_t N>
-void PushToVector(const T(&data)[N], std::vector<T>* buffer) {
- buffer->insert(buffer->end(), data, data + N);
-}
-
enum MidiEventType {
DISPATCH_SEND_MIDI_DATA,
};
@@ -71,9 +44,9 @@ struct MidiEvent {
double timestamp;
};
-class FakeMidiManager : public media::midi::MidiManager {
+class FakeMidiManager : public midi::MidiManager {
public:
- void DispatchSendMidiData(media::midi::MidiManagerClient* client,
+ void DispatchSendMidiData(midi::MidiManagerClient* client,
uint32_t port_index,
const std::vector<uint8_t>& data,
double timestamp) override {
@@ -88,7 +61,7 @@ class FakeMidiManager : public media::midi::MidiManager {
class MidiHostForTesting : public MidiHost {
public:
MidiHostForTesting(int renderer_process_id,
- media::midi::MidiManager* midi_manager)
+ midi::MidiManager* midi_manager)
: MidiHost(renderer_process_id, midi_manager) {}
private:
@@ -119,8 +92,8 @@ class MidiHostTest : public testing::Test {
const std::string manufacturer("yukatan");
const std::string name("doki-doki-pi-pine");
const std::string version("3.14159265359");
- media::midi::MidiPortState state = media::midi::MIDI_PORT_CONNECTED;
- media::midi::MidiPortInfo info(id, manufacturer, name, version, state);
+ PortState state = PortState::CONNECTED;
+ midi::MidiPortInfo info(id, manufacturer, name, version, state);
host_->AddOutputPort(info);
}
@@ -161,53 +134,6 @@ class MidiHostTest : public testing::Test {
} // namespace
-TEST_F(MidiHostTest, IsValidWebMIDIData) {
- // Test single event scenario
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kGMOn)));
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kGSOn)));
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kNoteOn)));
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kChannelPressure)));
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(AsVector(kTimingClock)));
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData1)));
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData2)));
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kBrokenData3)));
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(AsVector(kDataByte0)));
-
- // MIDI running status should be disallowed
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(
- AsVector(kNoteOnWithRunningStatus)));
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(
- AsVector(kChannelPressureWithRunningStatus)));
-
- // Multiple messages are allowed as long as each of them is complete.
- {
- std::vector<uint8_t> buffer;
- PushToVector(kGMOn, &buffer);
- PushToVector(kNoteOn, &buffer);
- PushToVector(kGSOn, &buffer);
- PushToVector(kTimingClock, &buffer);
- PushToVector(kNoteOn, &buffer);
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(buffer));
- PushToVector(kBrokenData1, &buffer);
- EXPECT_FALSE(MidiHost::IsValidWebMIDIData(buffer));
- }
-
- // MIDI realtime message can be placed at any position.
- {
- const uint8_t kNoteOnWithRealTimeClock[] = {
- 0x90, 0xf8, 0x3c, 0x7f, 0x90, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8,
- };
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(
- AsVector(kNoteOnWithRealTimeClock)));
-
- const uint8_t kGMOnWithRealTimeClock[] = {
- 0xf0, 0xf8, 0x7e, 0x7f, 0x09, 0x01, 0xf8, 0xf7,
- };
- EXPECT_TRUE(MidiHost::IsValidWebMIDIData(
- AsVector(kGMOnWithRealTimeClock)));
- }
-}
-
// Test if sending data to out of range port is ignored.
TEST_F(MidiHostTest, OutputPortCheck) {
// Only one output port is available.
diff --git a/chromium/content/browser/media/session/audio_focus_delegate.h b/chromium/content/browser/media/session/audio_focus_delegate.h
new file mode 100644
index 00000000000..5df555a56e5
--- /dev/null
+++ b/chromium/content/browser/media/session/audio_focus_delegate.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
+
+#include "content/browser/media/session/audio_focus_manager.h"
+
+namespace content {
+
+class MediaSessionImpl;
+
+// AudioFocusDelegate is an interface abstracting audio focus handling for the
+// MediaSession class.
+class AudioFocusDelegate {
+ public:
+ // Factory method returning an implementation of AudioFocusDelegate.
+ static std::unique_ptr<AudioFocusDelegate> Create(
+ MediaSessionImpl* media_session);
+
+ virtual ~AudioFocusDelegate() = default;
+
+ virtual bool RequestAudioFocus(
+ AudioFocusManager::AudioFocusType audio_focus_type) = 0;
+ virtual void AbandonAudioFocus() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_android.cc b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
new file mode 100644
index 00000000000..dfaba7d1588
--- /dev/null
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
@@ -0,0 +1,102 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/audio_focus_delegate_android.h"
+
+#include "base/android/context_utils.h"
+#include "base/android/jni_android.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "jni/AudioFocusDelegate_jni.h"
+
+using base::android::JavaParamRef;
+
+namespace content {
+
+// static
+bool AudioFocusDelegateAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+AudioFocusDelegateAndroid::AudioFocusDelegateAndroid(
+ MediaSessionImpl* media_session)
+ : media_session_(media_session) {}
+
+AudioFocusDelegateAndroid::~AudioFocusDelegateAndroid() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ Java_AudioFocusDelegate_tearDown(env, j_media_session_delegate_);
+}
+
+void AudioFocusDelegateAndroid::Initialize() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ j_media_session_delegate_.Reset(Java_AudioFocusDelegate_create(
+ env, base::android::GetApplicationContext(),
+ reinterpret_cast<intptr_t>(this)));
+}
+
+bool AudioFocusDelegateAndroid::RequestAudioFocus(
+ AudioFocusManager::AudioFocusType audio_focus_type) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ return Java_AudioFocusDelegate_requestAudioFocus(
+ env, j_media_session_delegate_,
+ audio_focus_type ==
+ AudioFocusManager::AudioFocusType::GainTransientMayDuck);
+}
+
+void AudioFocusDelegateAndroid::AbandonAudioFocus() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ Java_AudioFocusDelegate_abandonAudioFocus(env, j_media_session_delegate_);
+}
+
+void AudioFocusDelegateAndroid::OnSuspend(JNIEnv*,
+ const JavaParamRef<jobject>&,
+ jboolean temporary) {
+ // TODO(mlamouri): this check makes it so that if a MediaSession is paused and
+ // then loses audio focus, it will still stay in the Suspended state.
+ // See https://crbug.com/539998
+ if (!media_session_->IsActive())
+ return;
+
+ if (temporary) {
+ media_session_->Suspend(MediaSession::SuspendType::SYSTEM);
+ } else {
+ media_session_->Stop(MediaSession::SuspendType::SYSTEM);
+ }
+}
+
+void AudioFocusDelegateAndroid::OnResume(JNIEnv*,
+ const JavaParamRef<jobject>&) {
+ if (!media_session_->IsReallySuspended())
+ return;
+
+ media_session_->Resume(MediaSession::SuspendType::SYSTEM);
+}
+
+void AudioFocusDelegateAndroid::OnStartDucking(JNIEnv*, jobject) {
+ media_session_->StartDucking();
+}
+
+void AudioFocusDelegateAndroid::OnStopDucking(JNIEnv*, jobject) {
+ media_session_->StopDucking();
+}
+
+void AudioFocusDelegateAndroid::RecordSessionDuck(
+ JNIEnv*,
+ const JavaParamRef<jobject>&) {
+ media_session_->RecordSessionDuck();
+}
+
+// static
+std::unique_ptr<AudioFocusDelegate> AudioFocusDelegate::Create(
+ MediaSessionImpl* media_session) {
+ AudioFocusDelegateAndroid* delegate =
+ new AudioFocusDelegateAndroid(media_session);
+ delegate->Initialize();
+ return std::unique_ptr<AudioFocusDelegate>(delegate);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_delegate_android.h b/chromium/content/browser/media/session/audio_focus_delegate_android.h
index f498dd14daf..31a48ddc494 100644
--- a/chromium/content/browser/media/session/media_session_delegate_android.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.h
@@ -2,24 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
-#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_ANDROID_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_ANDROID_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
-#include "content/browser/media/session/media_session_delegate.h"
+#include "content/browser/media/session/audio_focus_delegate.h"
namespace content {
-// MediaSessionDelegateAndroid handles the audio focus at a system level on
+// AudioFocusDelegateAndroid handles the audio focus at a system level on
// Android. It is also proxying the JNI calls.
-class MediaSessionDelegateAndroid : public MediaSessionDelegate {
+class AudioFocusDelegateAndroid : public AudioFocusDelegate {
public:
static bool Register(JNIEnv* env);
- explicit MediaSessionDelegateAndroid(MediaSession* media_session);
- ~MediaSessionDelegateAndroid() override;
+ explicit AudioFocusDelegateAndroid(MediaSessionImpl* media_session);
+ ~AudioFocusDelegateAndroid() override;
void Initialize();
@@ -48,16 +48,16 @@ class MediaSessionDelegateAndroid : public MediaSessionDelegate {
// Record when the Android system requests the MediaSession to duck.
// Called by Java through JNI.
void RecordSessionDuck(JNIEnv* env,
- const base::android::JavaParamRef<jobject> &obj);
+ const base::android::JavaParamRef<jobject>& obj);
private:
// Weak pointer because |this| is owned by |media_session_|.
- MediaSession* media_session_;
+ MediaSessionImpl* media_session_;
base::android::ScopedJavaGlobalRef<jobject> j_media_session_delegate_;
- DISALLOW_COPY_AND_ASSIGN(MediaSessionDelegateAndroid);
+ DISALLOW_COPY_AND_ASSIGN(AudioFocusDelegateAndroid);
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_ANDROID_H_
diff --git a/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc b/chromium/content/browser/media/session/audio_focus_delegate_android_browsertest.cc
index e2d00a360cf..b49a064e29d 100644
--- a/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android_browsertest.cc
@@ -9,15 +9,15 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/media/session/media_session.h"
-#include "content/browser/media/session/mock_media_session_observer.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/browser/media/session/mock_media_session_player_observer.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h"
namespace content {
-class MediaSessionDelegateAndroidBrowserTest : public ContentBrowserTest {};
+class AudioFocusDelegateAndroidBrowserTest : public ContentBrowserTest {};
// MAYBE_OnAudioFocusChangeAfterDtorCrash will hit a DCHECK before the crash, it
// is the only way found to actually reproduce the crash so as a result, the
@@ -31,26 +31,28 @@ class MediaSessionDelegateAndroidBrowserTest : public ContentBrowserTest {};
DISABLED_OnAudioFocusChangeAfterDtorCrash
#endif
-IN_PROC_BROWSER_TEST_F(MediaSessionDelegateAndroidBrowserTest,
+IN_PROC_BROWSER_TEST_F(AudioFocusDelegateAndroidBrowserTest,
MAYBE_OnAudioFocusChangeAfterDtorCrash) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionPlayerObserver> player_observer(
+ new MockMediaSessionPlayerObserver);
- MediaSession* media_session = MediaSession::Get(shell()->web_contents());
+ MediaSessionImpl* media_session =
+ MediaSessionImpl::Get(shell()->web_contents());
ASSERT_TRUE(media_session);
WebContents* other_web_contents = CreateBrowser()->web_contents();
- MediaSession* other_media_session = MediaSession::Get(other_web_contents);
+ MediaSessionImpl* other_media_session =
+ MediaSessionImpl::Get(other_web_contents);
ASSERT_TRUE(other_media_session);
- media_session_observer->StartNewPlayer();
- media_session->AddPlayer(media_session_observer.get(), 0,
+ player_observer->StartNewPlayer();
+ media_session->AddPlayer(player_observer.get(), 0,
media::MediaContentType::Persistent);
EXPECT_TRUE(media_session->IsActive());
EXPECT_FALSE(other_media_session->IsActive());
- media_session_observer->StartNewPlayer();
- other_media_session->AddPlayer(media_session_observer.get(), 1,
+ player_observer->StartNewPlayer();
+ other_media_session->AddPlayer(player_observer.get(), 1,
media::MediaContentType::Persistent);
EXPECT_TRUE(media_session->IsActive());
EXPECT_TRUE(other_media_session->IsActive());
diff --git a/chromium/content/browser/media/session/media_session_delegate_default.cc b/chromium/content/browser/media/session/audio_focus_delegate_default.cc
index a921b071b2b..b1ae90f503f 100644
--- a/chromium/content/browser/media/session/media_session_delegate_default.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default.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/media/session/media_session_delegate.h"
+#include "content/browser/media/session/audio_focus_delegate.h"
#include "base/command_line.h"
#include "content/browser/media/session/audio_focus_manager.h"
@@ -14,36 +14,35 @@ using AudioFocusType = AudioFocusManager::AudioFocusType;
namespace {
-// MediaSessionDelegateDefault is the default implementation of
-// MediaSessionDelegate which only handles audio focus between WebContents.
-class MediaSessionDelegateDefault : public MediaSessionDelegate {
+// AudioFocusDelegateDefault is the default implementation of
+// AudioFocusDelegate which only handles audio focus between WebContents.
+class AudioFocusDelegateDefault : public AudioFocusDelegate {
public:
- explicit MediaSessionDelegateDefault(MediaSession* media_session);
- ~MediaSessionDelegateDefault() override;
+ explicit AudioFocusDelegateDefault(MediaSessionImpl* media_session);
+ ~AudioFocusDelegateDefault() override;
- // MediaSessionDelegate implementation.
+ // AudioFocusDelegate implementation.
bool RequestAudioFocus(
AudioFocusManager::AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override;
private:
// Weak pointer because |this| is owned by |media_session_|.
- MediaSession* media_session_;
+ MediaSessionImpl* media_session_;
};
} // anonymous namespace
-MediaSessionDelegateDefault::MediaSessionDelegateDefault(
- MediaSession* media_session)
- : media_session_(media_session) {
-}
+AudioFocusDelegateDefault::AudioFocusDelegateDefault(
+ MediaSessionImpl* media_session)
+ : media_session_(media_session) {}
-MediaSessionDelegateDefault::~MediaSessionDelegateDefault() = default;
+AudioFocusDelegateDefault::~AudioFocusDelegateDefault() = default;
-bool MediaSessionDelegateDefault::RequestAudioFocus(
+bool AudioFocusDelegateDefault::RequestAudioFocus(
AudioFocusManager::AudioFocusType audio_focus_type) {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableDefaultMediaSession)) {
+ switches::kEnableDefaultMediaSession)) {
return true;
}
@@ -52,15 +51,15 @@ bool MediaSessionDelegateDefault::RequestAudioFocus(
return true;
}
-void MediaSessionDelegateDefault::AbandonAudioFocus() {
+void AudioFocusDelegateDefault::AbandonAudioFocus() {
AudioFocusManager::GetInstance()->AbandonAudioFocus(media_session_);
}
// static
-std::unique_ptr<MediaSessionDelegate> MediaSessionDelegate::Create(
- MediaSession* media_session) {
- return std::unique_ptr<MediaSessionDelegate>(
- new MediaSessionDelegateDefault(media_session));
+std::unique_ptr<AudioFocusDelegate> AudioFocusDelegate::Create(
+ MediaSessionImpl* media_session) {
+ return std::unique_ptr<AudioFocusDelegate>(
+ new AudioFocusDelegateDefault(media_session));
}
} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
index 921c084636b..b84d38830f7 100644
--- a/chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "content/browser/media/session/media_session.h"
-#include "content/browser/media/session/mock_media_session_observer.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/browser/media/session/mock_media_session_player_observer.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h"
@@ -12,53 +12,54 @@
namespace content {
-class MediaSessionDelegateDefaultBrowserTest : public ContentBrowserTest {
+class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kEnableDefaultMediaSession);
}
void Run(WebContents* start_contents, WebContents* interrupt_contents) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionPlayerObserver>
+ player_observer(new MockMediaSessionPlayerObserver);
- MediaSession* media_session = MediaSession::Get(start_contents);
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(start_contents);
ASSERT_TRUE(media_session);
- MediaSession* other_media_session = MediaSession::Get(interrupt_contents);
+ MediaSessionImpl* other_media_session =
+ MediaSessionImpl::Get(interrupt_contents);
ASSERT_TRUE(other_media_session);
- media_session_observer->StartNewPlayer();
- media_session->AddPlayer(media_session_observer.get(), 0,
+ player_observer->StartNewPlayer();
+ media_session->AddPlayer(player_observer.get(), 0,
media::MediaContentType::Persistent);
EXPECT_TRUE(media_session->IsActive());
EXPECT_FALSE(other_media_session->IsActive());
- media_session_observer->StartNewPlayer();
- other_media_session->AddPlayer(media_session_observer.get(), 1,
+ player_observer->StartNewPlayer();
+ other_media_session->AddPlayer(player_observer.get(), 1,
media::MediaContentType::Persistent);
EXPECT_FALSE(media_session->IsActive());
EXPECT_TRUE(other_media_session->IsActive());
- media_session->Stop(MediaSession::SuspendType::UI);
- other_media_session->Stop(MediaSession::SuspendType::UI);
+ media_session->Stop(MediaSessionImpl::SuspendType::UI);
+ other_media_session->Stop(MediaSessionImpl::SuspendType::UI);
}
};
// Two windows from the same BrowserContext.
-IN_PROC_BROWSER_TEST_F(MediaSessionDelegateDefaultBrowserTest,
+IN_PROC_BROWSER_TEST_F(AudioFocusDelegateDefaultBrowserTest,
ActiveWebContentsPauseOthers) {
Run(shell()->web_contents(), CreateBrowser()->web_contents());
}
// Regular BrowserContext is interrupted by OffTheRecord one.
-IN_PROC_BROWSER_TEST_F(MediaSessionDelegateDefaultBrowserTest,
+IN_PROC_BROWSER_TEST_F(AudioFocusDelegateDefaultBrowserTest,
RegularBrowserInterruptsOffTheRecord) {
Run(shell()->web_contents(), CreateOffTheRecordBrowser()->web_contents());
}
// OffTheRecord BrowserContext is interrupted by regular one.
-IN_PROC_BROWSER_TEST_F(MediaSessionDelegateDefaultBrowserTest,
+IN_PROC_BROWSER_TEST_F(AudioFocusDelegateDefaultBrowserTest,
OffTheRecordInterruptsRegular) {
Run(CreateOffTheRecordBrowser()->web_contents(), shell()->web_contents());
}
diff --git a/chromium/content/browser/media/session/audio_focus_manager.cc b/chromium/content/browser/media/session/audio_focus_manager.cc
index cad3c5e2923..48f6dcce962 100644
--- a/chromium/content/browser/media/session/audio_focus_manager.cc
+++ b/chromium/content/browser/media/session/audio_focus_manager.cc
@@ -5,7 +5,7 @@
#include "content/browser/media/session/audio_focus_manager.h"
#include "base/memory/ptr_util.h"
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/public/browser/web_contents.h"
namespace content {
@@ -15,7 +15,7 @@ AudioFocusManager* AudioFocusManager::GetInstance() {
return base::Singleton<AudioFocusManager>::get();
}
-void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
+void AudioFocusManager::RequestAudioFocus(MediaSessionImpl* media_session,
AudioFocusType type) {
if (!audio_focus_stack_.empty() &&
audio_focus_stack_.back() == media_session &&
@@ -28,9 +28,10 @@ void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
MaybeRemoveFocusEntry(media_session);
- // TODO(zqzhang): It seems like MediaSession is exposed to AudioFocusManager
+ // TODO(zqzhang): It seems like MediaSessionImpl is exposed to
+ // AudioFocusManager
// too much. Maybe it's better to do some abstraction and refactoring to clean
- // up the relation between AudioFocusManager and MediaSession.
+ // up the relation between AudioFocusManager and MediaSessionImpl.
// See https://crbug.com/651069
if (type == AudioFocusType::GainTransientMayDuck) {
for (const auto old_session : audio_focus_stack_) {
@@ -42,7 +43,7 @@ void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
if (old_session->HasPepper())
old_session->StartDucking();
else
- old_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ old_session->Suspend(MediaSessionImpl::SuspendType::SYSTEM);
}
}
}
@@ -51,7 +52,7 @@ void AudioFocusManager::RequestAudioFocus(MediaSession* media_session,
audio_focus_stack_.back()->StopDucking();
}
-void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
+void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
if (audio_focus_stack_.empty())
return;
@@ -64,20 +65,22 @@ void AudioFocusManager::AbandonAudioFocus(MediaSession* media_session) {
if (audio_focus_stack_.empty())
return;
- // Allow the top-most MediaSession having Pepper to unduck pepper even if it's
+ // Allow the top-most MediaSessionImpl having Pepper to unduck pepper even if
+ // it's
// not active.
for (auto iter = audio_focus_stack_.rbegin();
iter != audio_focus_stack_.rend(); ++iter) {
if (!(*iter)->HasPepper())
continue;
- MediaSession* pepper_session = *iter;
+ MediaSessionImpl* pepper_session = *iter;
pepper_session->StopDucking();
MaybeRemoveFocusEntry(pepper_session);
audio_focus_stack_.push_back(pepper_session);
return;
}
- // Only try to unduck the new MediaSession on top. The session might be still
+ // Only try to unduck the new MediaSessionImpl on top. The session might be
+ // still
// inactive but it will not be resumed (so it doesn't surprise the user).
audio_focus_stack_.back()->StopDucking();
}
@@ -86,7 +89,7 @@ AudioFocusManager::AudioFocusManager() = default;
AudioFocusManager::~AudioFocusManager() = default;
-void AudioFocusManager::MaybeRemoveFocusEntry(MediaSession* media_session) {
+void AudioFocusManager::MaybeRemoveFocusEntry(MediaSessionImpl* media_session) {
audio_focus_stack_.remove(media_session);
}
diff --git a/chromium/content/browser/media/session/audio_focus_manager.h b/chromium/content/browser/media/session/audio_focus_manager.h
index 9cbf13f06da..df49b85fc1f 100644
--- a/chromium/content/browser/media/session/audio_focus_manager.h
+++ b/chromium/content/browser/media/session/audio_focus_manager.h
@@ -14,7 +14,7 @@
namespace content {
-class MediaSession;
+class MediaSessionImpl;
class CONTENT_EXPORT AudioFocusManager {
public:
@@ -26,9 +26,9 @@ class CONTENT_EXPORT AudioFocusManager {
// Returns Chromium's internal AudioFocusManager.
static AudioFocusManager* GetInstance();
- void RequestAudioFocus(MediaSession* media_session, AudioFocusType type);
+ void RequestAudioFocus(MediaSessionImpl* media_session, AudioFocusType type);
- void AbandonAudioFocus(MediaSession* media_session);
+ void AbandonAudioFocus(MediaSessionImpl* media_session);
private:
friend struct base::DefaultSingletonTraits<AudioFocusManager>;
@@ -37,11 +37,11 @@ class CONTENT_EXPORT AudioFocusManager {
AudioFocusManager();
~AudioFocusManager();
- void MaybeRemoveFocusEntry(MediaSession* media_session);
+ void MaybeRemoveFocusEntry(MediaSessionImpl* media_session);
// Weak reference of managed MediaSessions. A MediaSession must abandon audio
// foucs before its destruction.
- std::list<MediaSession*> audio_focus_stack_;
+ std::list<MediaSessionImpl*> audio_focus_stack_;
};
} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
index df66e862491..37c577cf7a4 100644
--- a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
+++ b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
@@ -5,8 +5,8 @@
#include "content/browser/media/session/audio_focus_manager.h"
#include "base/command_line.h"
-#include "content/browser/media/session/media_session.h"
-#include "content/browser/media/session/media_session_observer.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/browser/media/session/media_session_player_observer.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread.h"
@@ -18,7 +18,7 @@ namespace content {
namespace {
-class MockMediaSessionObserver : public MediaSessionObserver {
+class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
public:
void OnSuspend(int player_id) override {}
void OnResume(int player_id) override {}
@@ -41,7 +41,7 @@ class AudioFocusManagerTest : public testing::Test {
rph_factory_.reset(new MockRenderProcessHostFactory());
SiteInstanceImpl::set_render_process_host_factory(rph_factory_.get());
browser_context_.reset(new TestBrowserContext());
- pepper_observer_.reset(new MockMediaSessionObserver());
+ pepper_observer_.reset(new MockMediaSessionPlayerObserver());
}
void TearDown() override {
@@ -50,7 +50,7 @@ class AudioFocusManagerTest : public testing::Test {
rph_factory_.reset();
}
- MediaSession* GetAudioFocusedSession() const {
+ MediaSessionImpl* GetAudioFocusedSession() const {
const auto& audio_focus_stack =
AudioFocusManager::GetInstance()->audio_focus_stack_;
for (auto iter = audio_focus_stack.rbegin();
@@ -79,16 +79,16 @@ class AudioFocusManagerTest : public testing::Test {
return count;
}
- double IsSessionDucking(MediaSession* session) {
+ double IsSessionDucking(MediaSessionImpl* session) {
return session->is_ducking_; // Quack! Quack!
}
- void RequestAudioFocus(MediaSession* session,
+ void RequestAudioFocus(MediaSessionImpl* session,
AudioFocusManager::AudioFocusType audio_focus_type) {
session->RequestSystemAudioFocus(audio_focus_type);
}
- void AbandonAudioFocus(MediaSession* session) {
+ void AbandonAudioFocus(MediaSessionImpl* session) {
session->AbandonSystemAudioFocusIfNeeded();
}
@@ -97,7 +97,7 @@ class AudioFocusManagerTest : public testing::Test {
SiteInstance::SiteInstance::Create(browser_context_.get()));
}
- std::unique_ptr<MediaSessionObserver> pepper_observer_;
+ std::unique_ptr<MediaSessionPlayerObserver> pepper_observer_;
private:
base::MessageLoopForUI message_loop_;
@@ -115,13 +115,16 @@ TEST_F(AudioFocusManagerTest, InstanceAvailableAndSame) {
TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSession* media_session_3 = MediaSession::Get(web_contents_3.get());
+ MediaSessionImpl* media_session_3 =
+ MediaSessionImpl::Get(web_contents_3.get());
ASSERT_EQ(nullptr, GetAudioFocusedSession());
@@ -137,7 +140,7 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
ASSERT_EQ(nullptr, GetAudioFocusedSession());
@@ -150,7 +153,7 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(
media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
@@ -164,7 +167,7 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
@@ -179,10 +182,12 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
@@ -201,7 +206,7 @@ TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
@@ -212,7 +217,7 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_NoAssociatedEntry) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
AbandonAudioFocus(media_session);
ASSERT_EQ(nullptr, GetAudioFocusedSession());
@@ -220,7 +225,7 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_NoAssociatedEntry) {
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(
media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
@@ -232,10 +237,12 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
@@ -258,10 +265,12 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
@@ -279,10 +288,12 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
TEST_F(AudioFocusManagerTest, DuckWhilePlaying) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
@@ -294,10 +305,12 @@ TEST_F(AudioFocusManagerTest, DuckWhilePlaying) {
TEST_F(AudioFocusManagerTest, GainSuspendsTransient) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(
media_session_2, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
@@ -308,13 +321,16 @@ TEST_F(AudioFocusManagerTest, GainSuspendsTransient) {
TEST_F(AudioFocusManagerTest, DuckWithMultipleTransients) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSession* media_session_3 = MediaSession::Get(web_contents_3.get());
+ MediaSessionImpl* media_session_3 =
+ MediaSessionImpl::Get(web_contents_3.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
@@ -336,7 +352,7 @@ TEST_F(AudioFocusManagerTest, DuckWithMultipleTransients) {
TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesFocus) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(media_session, AudioFocusManager::AudioFocusType::Gain);
ASSERT_EQ(media_session, GetAudioFocusedSession());
@@ -347,7 +363,7 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesFocus) {
TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesTransients) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
RequestAudioFocus(
media_session, AudioFocusManager::AudioFocusType::GainTransientMayDuck);
@@ -359,10 +375,12 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesTransients) {
TEST_F(AudioFocusManagerTest, WebContentsDestroyed_StopsDucking) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
RequestAudioFocus(media_session_1, AudioFocusManager::AudioFocusType::Gain);
ASSERT_FALSE(IsSessionDucking(media_session_1));
@@ -377,7 +395,7 @@ TEST_F(AudioFocusManagerTest, WebContentsDestroyed_StopsDucking) {
TEST_F(AudioFocusManagerTest, PepperRequestsGainFocus) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSession* media_session = MediaSession::Get(web_contents.get());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
media_session->AddPlayer(
pepper_observer_.get(), 0, media::MediaContentType::Pepper);
@@ -389,10 +407,12 @@ TEST_F(AudioFocusManagerTest, PepperRequestsGainFocus) {
TEST_F(AudioFocusManagerTest, GainDucksPepper) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
media_session_1->AddPlayer(
pepper_observer_.get(), 0, media::MediaContentType::Pepper);
@@ -407,13 +427,16 @@ TEST_F(AudioFocusManagerTest, GainDucksPepper) {
TEST_F(AudioFocusManagerTest, AbandoningGainFocusRevokesTopMostPepperSession) {
std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSession* media_session_1 = MediaSession::Get(web_contents_1.get());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSession* media_session_2 = MediaSession::Get(web_contents_2.get());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSession* media_session_3 = MediaSession::Get(web_contents_3.get());
+ MediaSessionImpl* media_session_3 =
+ MediaSessionImpl::Get(web_contents_3.get());
media_session_1->AddPlayer(
pepper_observer_.get(), 0, media::MediaContentType::Pepper);
diff --git a/chromium/content/browser/media/session/media_metadata_sanitizer.cc b/chromium/content/browser/media/session/media_metadata_sanitizer.cc
new file mode 100644
index 00000000000..0a53baae79b
--- /dev/null
+++ b/chromium/content/browser/media/session/media_metadata_sanitizer.cc
@@ -0,0 +1,111 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_metadata_sanitizer.h"
+
+#include <algorithm>
+#include <string>
+
+#include "content/public/common/media_metadata.h"
+
+namespace content {
+
+namespace {
+
+// Maximum length for all the strings inside the MediaMetadata when it is sent
+// over IPC. The renderer process should truncate the strings before sending
+// the MediaMetadata and the browser process must do the same when receiving
+// it.
+const size_t kMaxIPCStringLength = 4 * 1024;
+
+// Maximum type length of MediaImage, which conforms to RFC 4288
+// (https://tools.ietf.org/html/rfc4288).
+const size_t kMaxMediaImageTypeLength = 2 * 127 + 1;
+
+// Maximum number of MediaImages inside the MediaMetadata.
+const size_t kMaxNumberOfMediaImages = 10;
+
+// Maximum of sizes in a MediaImage.
+const size_t kMaxNumberOfMediaImageSizes = 10;
+
+bool CheckMediaImageSrcSanity(const GURL& src) {
+ if (!src.is_valid())
+ return false;
+ if (!src.SchemeIsHTTPOrHTTPS() && !src.SchemeIs(url::kDataScheme))
+ return false;
+ if (src.spec().size() > url::kMaxURLChars)
+ return false;
+
+ return true;
+}
+
+bool CheckMediaImageSanity(const MediaMetadata::MediaImage& image) {
+ if (!CheckMediaImageSrcSanity(image.src))
+ return false;
+ if (image.type.size() > kMaxMediaImageTypeLength)
+ return false;
+ if (image.sizes.size() > kMaxNumberOfMediaImageSizes)
+ return false;
+
+ return true;
+}
+
+// Sanitize MediaImage. The method should not be called if |image.src| is bad.
+MediaMetadata::MediaImage SanitizeMediaImage(
+ const MediaMetadata::MediaImage& image) {
+ MediaMetadata::MediaImage sanitized_image;
+
+ sanitized_image.src = image.src;
+ sanitized_image.type = image.type.substr(0, kMaxMediaImageTypeLength);
+ for (const auto& size : image.sizes) {
+ sanitized_image.sizes.push_back(size);
+ if (sanitized_image.sizes.size() == kMaxNumberOfMediaImageSizes)
+ break;
+ }
+
+ return sanitized_image;
+}
+
+} // anonymous namespace
+
+bool MediaMetadataSanitizer::CheckSanity(const MediaMetadata& metadata) {
+ if (metadata.title.size() > kMaxIPCStringLength)
+ return false;
+ if (metadata.artist.size() > kMaxIPCStringLength)
+ return false;
+ if (metadata.album.size() > kMaxIPCStringLength)
+ return false;
+ if (metadata.artwork.size() > kMaxNumberOfMediaImages)
+ return false;
+
+ for (const auto& image : metadata.artwork) {
+ if (!CheckMediaImageSanity(image))
+ return false;
+ }
+
+ return true;
+}
+
+MediaMetadata MediaMetadataSanitizer::Sanitize(const MediaMetadata& metadata) {
+ MediaMetadata sanitized_metadata;
+
+ sanitized_metadata.title = metadata.title.substr(0, kMaxIPCStringLength);
+ sanitized_metadata.artist = metadata.artist.substr(0, kMaxIPCStringLength);
+ sanitized_metadata.album = metadata.album.substr(0, kMaxIPCStringLength);
+
+ for (const auto& image : metadata.artwork) {
+ if (!CheckMediaImageSrcSanity(image.src))
+ continue;
+
+ sanitized_metadata.artwork.push_back(
+ CheckMediaImageSanity(image) ? image : SanitizeMediaImage(image));
+
+ if (sanitized_metadata.artwork.size() == kMaxNumberOfMediaImages)
+ break;
+ }
+
+ return sanitized_metadata;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_metadata_sanitizer.h b/chromium/content/browser/media/session/media_metadata_sanitizer.h
new file mode 100644
index 00000000000..e3a613a02e1
--- /dev/null
+++ b/chromium/content/browser/media/session/media_metadata_sanitizer.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_METADATA_SANITIZER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_METADATA_SANITIZER_H_
+
+namespace content {
+
+struct MediaMetadata;
+
+class MediaMetadataSanitizer {
+ public:
+ // Check the sanity of |metadata|.
+ static bool CheckSanity(const MediaMetadata& metadata);
+
+ // Sanitizes |metadata| and return the result.
+ static MediaMetadata Sanitize(const MediaMetadata& metadata);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_METADATA_SANITIZER_H_
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc
new file mode 100644
index 00000000000..87971b4b570
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_android.cc
@@ -0,0 +1,172 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_android.h"
+
+#include <algorithm>
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/browser/web_contents/web_contents_android.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/android/media_metadata_android.h"
+#include "content/public/browser/media_session.h"
+#include "jni/MediaSessionImpl_jni.h"
+
+namespace content {
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+struct MediaSessionAndroid::JavaObjectGetter {
+ static ScopedJavaLocalRef<jobject> GetJavaObject(
+ MediaSessionAndroid* session_android) {
+ return session_android->GetJavaObject();
+ }
+};
+
+MediaSessionAndroid::MediaSessionAndroid(MediaSessionImpl* session)
+ : MediaSessionObserver(session) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_media_session =
+ Java_MediaSessionImpl_create(env, reinterpret_cast<intptr_t>(this));
+ j_media_session_ = JavaObjectWeakGlobalRef(env, j_media_session);
+
+ WebContentsAndroid* contents_android = GetWebContentsAndroid();
+ if (contents_android)
+ contents_android->SetMediaSession(j_media_session);
+}
+
+MediaSessionAndroid::~MediaSessionAndroid() = default;
+
+// static
+bool MediaSessionAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// static
+ScopedJavaLocalRef<jobject> GetMediaSessionFromWebContents(
+ JNIEnv* env,
+ const JavaParamRef<jclass>& clazz,
+ const JavaParamRef<jobject>& j_contents_android) {
+ WebContents* contents = WebContents::FromJavaWebContents(j_contents_android);
+ if (!contents)
+ return ScopedJavaLocalRef<jobject>();
+
+ MediaSessionImpl* session = MediaSessionImpl::Get(contents);
+ DCHECK(session);
+ return MediaSessionAndroid::JavaObjectGetter::GetJavaObject(
+ session->session_android());
+}
+
+void MediaSessionAndroid::MediaSessionDestroyed() {
+ ScopedJavaLocalRef<jobject> j_local_session = GetJavaObject();
+ if (j_local_session.is_null())
+ return;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ // The Java object will tear down after this call.
+ Java_MediaSessionImpl_mediaSessionDestroyed(env, j_local_session);
+ j_media_session_.reset();
+
+ WebContentsAndroid* contents_android = GetWebContentsAndroid();
+ if (contents_android)
+ contents_android->SetMediaSession(nullptr);
+}
+
+void MediaSessionAndroid::MediaSessionStateChanged(bool is_controllable,
+ bool is_suspended) {
+ ScopedJavaLocalRef<jobject> j_local_session = GetJavaObject();
+ if (j_local_session.is_null())
+ return;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MediaSessionImpl_mediaSessionStateChanged(env, j_local_session,
+ is_controllable, is_suspended);
+}
+
+void MediaSessionAndroid::MediaSessionMetadataChanged(
+ const base::Optional<MediaMetadata>& metadata) {
+ ScopedJavaLocalRef<jobject> j_local_session = GetJavaObject();
+ if (j_local_session.is_null())
+ return;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ // Avoid translating metadata through JNI if there is no Java observer.
+ if (!Java_MediaSessionImpl_hasObservers(env, j_local_session))
+ return;
+
+ ScopedJavaLocalRef<jobject> j_metadata;
+ if (metadata.has_value())
+ j_metadata = MediaMetadataAndroid::CreateJavaObject(env, metadata.value());
+ Java_MediaSessionImpl_mediaSessionMetadataChanged(env, j_local_session,
+ j_metadata);
+}
+
+void MediaSessionAndroid::MediaSessionEnabledAction(
+ blink::mojom::MediaSessionAction action) {
+ ScopedJavaLocalRef<jobject> j_local_session = GetJavaObject();
+ if (j_local_session.is_null())
+ return;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MediaSessionImpl_mediaSessionEnabledAction(env, j_local_session,
+ static_cast<int>(action));
+}
+
+void MediaSessionAndroid::MediaSessionDisabledAction(
+ blink::mojom::MediaSessionAction action) {
+ ScopedJavaLocalRef<jobject> j_local_session = GetJavaObject();
+ if (j_local_session.is_null())
+ return;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MediaSessionImpl_mediaSessionDisabledAction(env, j_local_session,
+ static_cast<int>(action));
+}
+
+void MediaSessionAndroid::Resume(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj) {
+ DCHECK(media_session());
+ media_session()->Resume(MediaSession::SuspendType::UI);
+}
+
+void MediaSessionAndroid::Suspend(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj) {
+ DCHECK(media_session());
+ media_session()->Suspend(MediaSession::SuspendType::UI);
+}
+
+void MediaSessionAndroid::Stop(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj) {
+ DCHECK(media_session());
+ media_session()->Stop(MediaSession::SuspendType::UI);
+}
+
+void MediaSessionAndroid::DidReceiveAction(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ int action) {
+ media_session()->DidReceiveAction(
+ static_cast<blink::mojom::MediaSessionAction>(action));
+}
+
+WebContentsAndroid* MediaSessionAndroid::GetWebContentsAndroid() {
+ MediaSessionImpl* session = static_cast<MediaSessionImpl*>(media_session());
+ if (!session)
+ return nullptr;
+ WebContentsImpl* contents =
+ static_cast<WebContentsImpl*>(session->web_contents());
+ if (!contents)
+ return nullptr;
+ return contents->GetWebContentsAndroid();
+}
+
+ScopedJavaLocalRef<jobject> MediaSessionAndroid::GetJavaObject() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return j_media_session_.get(env);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_android.h b/chromium/content/browser/media/session/media_session_android.h
new file mode 100644
index 00000000000..2b403197cd6
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_android.h
@@ -0,0 +1,69 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_ANDROID_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_ANDROID_H_
+
+#include <jni.h>
+#include <memory>
+#include <vector>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "content/public/browser/media_session_observer.h"
+
+namespace content {
+
+class MediaSessionImpl;
+class WebContentsAndroid;
+
+// This class is interlayer between native MediaSession and Java
+// MediaSession. This class is owned by the native MediaSession and will
+// teardown Java MediaSession when the native MediaSession is destroyed.
+// Java MediaSessionObservers are also proxied via this class.
+class MediaSessionAndroid final : public MediaSessionObserver {
+ public:
+ // Helper class for calling GetJavaObject() in a static method, in order to
+ // avoid leaking the Java object outside.
+ struct JavaObjectGetter;
+
+ static bool Register(JNIEnv* env);
+
+ explicit MediaSessionAndroid(MediaSessionImpl* session);
+ ~MediaSessionAndroid() override;
+
+ // MediaSessionObserver implementation.
+ void MediaSessionDestroyed() override;
+ void MediaSessionStateChanged(bool is_controllable,
+ bool is_suspended) override;
+ void MediaSessionMetadataChanged(
+ const base::Optional<MediaMetadata>& metadata) override;
+ void MediaSessionEnabledAction(
+ blink::mojom::MediaSessionAction action) override;
+ void MediaSessionDisabledAction(
+ blink::mojom::MediaSessionAction action) override;
+
+ // MediaSession method wrappers.
+ void Resume(JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj);
+ void Suspend(JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj);
+ void Stop(JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj);
+ void DidReceiveAction(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj,
+ jint action);
+
+ private:
+ WebContentsAndroid* GetWebContentsAndroid();
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ // The linked Java object. The strong reference is hold by Java WebContensImpl
+ // to avoid introducing a new GC root.
+ JavaObjectWeakGlobalRef j_media_session_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_ANDROID_H_
diff --git a/chromium/content/browser/media/session/media_session_browsertest.cc b/chromium/content/browser/media/session/media_session_browsertest.cc
deleted file mode 100644
index 629c562c0f6..00000000000
--- a/chromium/content/browser/media/session/media_session_browsertest.cc
+++ /dev/null
@@ -1,1347 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/session/media_session.h"
-
-#include <stddef.h>
-
-#include <list>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "content/browser/media/session/media_session_delegate.h"
-#include "content/browser/media/session/mock_media_session_observer.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/shell/browser/shell.h"
-#include "media/base/media_content_type.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using content::WebContents;
-using content::WebContentsObserver;
-using content::MediaSession;
-using content::MediaSessionDelegate;
-using content::MediaSessionObserver;
-using content::MediaSessionUmaHelper;
-using content::MockMediaSessionObserver;
-
-using ::testing::Expectation;
-
-namespace {
-
-const double kDefaultVolumeMultiplier = 1.0;
-const double kDuckingVolumeMultiplier = 0.2;
-
-class MockMediaSessionDelegate : public MediaSessionDelegate {
- public:
- bool RequestAudioFocus(content::AudioFocusManager::AudioFocusType) override {
- return true;
- }
-
- void AbandonAudioFocus() override {
- }
-};
-
-class MockWebContentsObserver : public WebContentsObserver {
- public:
- MockWebContentsObserver(WebContents* web_contents)
- : WebContentsObserver(web_contents) {}
-
- MOCK_METHOD3(MediaSessionStateChanged,
- void(bool is_controllable, bool is_suspended,
- const base::Optional<content::MediaMetadata>& metadata));
-};
-
-} // namespace
-
-class MediaSessionBrowserTest : public content::ContentBrowserTest {
- protected:
- MediaSessionBrowserTest() = default;
-
- void SetUpOnMainThread() override {
- ContentBrowserTest::SetUpOnMainThread();
-
- mock_web_contents_observer_.reset(
- new MockWebContentsObserver(shell()->web_contents()));
- media_session_ = MediaSession::Get(shell()->web_contents());
- media_session_->SetDelegateForTests(
- std::unique_ptr<MediaSessionDelegate>(new MockMediaSessionDelegate()));
- ASSERT_TRUE(media_session_);
- }
-
- void TearDownOnMainThread() override {
- mock_web_contents_observer_.reset();
-
- media_session_->RemoveAllPlayersForTest();
- media_session_ = nullptr;
-
- ContentBrowserTest::TearDownOnMainThread();
- }
-
- void StartNewPlayer(MockMediaSessionObserver* media_session_observer,
- media::MediaContentType media_content_type) {
- bool result =
- AddPlayer(media_session_observer,
- media_session_observer->StartNewPlayer(), media_content_type);
- EXPECT_TRUE(result);
- }
-
- bool AddPlayer(MockMediaSessionObserver* media_session_observer,
- int player_id,
- media::MediaContentType type) {
- return media_session_->AddPlayer(media_session_observer, player_id, type);
- }
-
- void RemovePlayer(MockMediaSessionObserver* media_session_observer,
- int player_id) {
- media_session_->RemovePlayer(media_session_observer, player_id);
- }
-
- void RemovePlayers(MockMediaSessionObserver* media_session_observer) {
- media_session_->RemovePlayers(media_session_observer);
- }
-
- void OnPlayerPaused(MockMediaSessionObserver* media_session_observer,
- int player_id) {
- media_session_->OnPlayerPaused(media_session_observer, player_id);
- }
-
- bool HasAudioFocus() { return media_session_->IsActiveForTest(); }
-
- content::AudioFocusManager::AudioFocusType GetSessionAudioFocusType() {
- return media_session_->audio_focus_type();
- }
-
- bool IsControllable() { return media_session_->IsControllable(); }
-
- bool IsSuspended() { return media_session_->IsSuspended(); }
-
- void UIResume() {
- media_session_->Resume(MediaSession::SuspendType::UI);
- }
-
- void SystemResume() {
- media_session_->OnResumeInternal(MediaSession::SuspendType::SYSTEM);
- }
-
- void UISuspend() {
- media_session_->Suspend(MediaSession::SuspendType::UI);
- }
-
- void SystemSuspend(bool temporary) {
- media_session_->OnSuspendInternal(
- MediaSession::SuspendType::SYSTEM,
- temporary ? MediaSession::State::SUSPENDED
- : MediaSession::State::INACTIVE);
- }
-
- void SystemStartDucking() {
- media_session_->StartDucking();
- }
-
- void SystemStopDucking() {
- media_session_->StopDucking();
- }
-
- MockWebContentsObserver* mock_web_contents_observer() {
- return mock_web_contents_observer_.get();
- }
-
- std::unique_ptr<MediaSession> CreateDummyMediaSession() {
- return std::unique_ptr<MediaSession>(new MediaSession(nullptr));
- }
-
- MediaSessionUmaHelper* GetMediaSessionUMAHelper() {
- return media_session_->uma_helper_for_test();
- }
-
- protected:
- MediaSession* media_session_;
- std::unique_ptr<MockWebContentsObserver> mock_web_contents_observer_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaSessionBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- PlayersFromSameObserverDoNotStopEachOtherInSameSession) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
- EXPECT_TRUE(media_session_observer->IsPlaying(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- PlayersFromManyObserverDoNotStopEachOtherInSameSession) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
- new MockMediaSessionObserver);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
- new MockMediaSessionObserver);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_3(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer_1.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_2.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_3.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(media_session_observer_1->IsPlaying(0));
- EXPECT_TRUE(media_session_observer_2->IsPlaying(0));
- EXPECT_TRUE(media_session_observer_3->IsPlaying(0));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- SuspendedMediaSessionStopsPlayers) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
-
- EXPECT_FALSE(media_session_observer->IsPlaying(0));
- EXPECT_FALSE(media_session_observer->IsPlaying(1));
- EXPECT_FALSE(media_session_observer->IsPlaying(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ResumedMediaSessionRestartsPlayers) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
- SystemResume();
-
- EXPECT_TRUE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
- EXPECT_TRUE(media_session_observer->IsPlaying(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- StartedPlayerOnSuspendedSessionPlaysAlone) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(media_session_observer->IsPlaying(0));
-
- SystemSuspend(true);
-
- EXPECT_FALSE(media_session_observer->IsPlaying(0));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_FALSE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_FALSE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
- EXPECT_TRUE(media_session_observer->IsPlaying(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- InitialVolumeMultiplier) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_EQ(kDefaultVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(0));
- EXPECT_EQ(kDefaultVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(1));
-
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- StartDuckingReducesVolumeMultiplier) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemStartDucking();
-
- EXPECT_EQ(kDuckingVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(0));
- EXPECT_EQ(kDuckingVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(1));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_EQ(kDuckingVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- StopDuckingRecoversVolumeMultiplier) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemStartDucking();
- SystemStopDucking();
-
- EXPECT_EQ(kDefaultVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(0));
- EXPECT_EQ(kDefaultVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(1));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_EQ(kDefaultVolumeMultiplier,
- media_session_observer->GetVolumeMultiplier(2));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, AudioFocusInitialState) {
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, StartPlayerGivesFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SuspendGivesAwayAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
-
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, StopGivesAwayAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeGivesBackAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
- SystemResume();
-
- EXPECT_TRUE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- RemovingLastPlayerDropsAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayer(media_session_observer.get(), 0);
- EXPECT_TRUE(HasAudioFocus());
- RemovePlayer(media_session_observer.get(), 1);
- EXPECT_TRUE(HasAudioFocus());
- RemovePlayer(media_session_observer.get(), 2);
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- RemovingLastPlayerFromManyObserversDropsAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
- new MockMediaSessionObserver);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
- new MockMediaSessionObserver);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_3(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer_1.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_2.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_3.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayer(media_session_observer_1.get(), 0);
- EXPECT_TRUE(HasAudioFocus());
- RemovePlayer(media_session_observer_2.get(), 0);
- EXPECT_TRUE(HasAudioFocus());
- RemovePlayer(media_session_observer_3.get(), 0);
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- RemovingAllPlayersFromObserversDropsAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
- new MockMediaSessionObserver);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer_1.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_1.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_2.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer_2.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayers(media_session_observer_1.get());
- EXPECT_TRUE(HasAudioFocus());
- RemovePlayers(media_session_observer_2.get());
- EXPECT_FALSE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumePlayGivesAudioFocus) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayer(media_session_observer.get(), 0);
- EXPECT_FALSE(HasAudioFocus());
-
- EXPECT_TRUE(AddPlayer(media_session_observer.get(), 0,
- media::MediaContentType::Persistent));
- EXPECT_TRUE(HasAudioFocus());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ResumeSuspendAreSentOnlyOncePerPlayers) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_EQ(0, media_session_observer->received_suspend_calls());
- EXPECT_EQ(0, media_session_observer->received_resume_calls());
-
- SystemSuspend(true);
- EXPECT_EQ(3, media_session_observer->received_suspend_calls());
-
- SystemResume();
- EXPECT_EQ(3, media_session_observer->received_resume_calls());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ResumeSuspendAreSentOnlyOncePerPlayersAddedTwice) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- // Adding the three players above again.
- EXPECT_TRUE(AddPlayer(media_session_observer.get(), 0,
- media::MediaContentType::Persistent));
- EXPECT_TRUE(AddPlayer(media_session_observer.get(), 1,
- media::MediaContentType::Persistent));
- EXPECT_TRUE(AddPlayer(media_session_observer.get(), 2,
- media::MediaContentType::Persistent));
-
- EXPECT_EQ(0, media_session_observer->received_suspend_calls());
- EXPECT_EQ(0, media_session_observer->received_resume_calls());
-
- SystemSuspend(true);
- EXPECT_EQ(3, media_session_observer->received_suspend_calls());
-
- SystemResume();
- EXPECT_EQ(3, media_session_observer->received_resume_calls());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- RemovingTheSamePlayerTwiceIsANoop) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayer(media_session_observer.get(), 0);
- RemovePlayer(media_session_observer.get(), 0);
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, AudioFocusType) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- // Starting a player with a given type should set the session to that type.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
- GetSessionAudioFocusType());
-
- // Adding a player of the same type should have no effect on the type.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
- GetSessionAudioFocusType());
-
- // Adding a player of Content type should override the current type.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
-
- // Adding a player of the Transient type should have no effect on the type.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
-
- EXPECT_TRUE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
- EXPECT_TRUE(media_session_observer->IsPlaying(2));
- EXPECT_TRUE(media_session_observer->IsPlaying(3));
-
- SystemSuspend(true);
-
- EXPECT_FALSE(media_session_observer->IsPlaying(0));
- EXPECT_FALSE(media_session_observer->IsPlaying(1));
- EXPECT_FALSE(media_session_observer->IsPlaying(2));
- EXPECT_FALSE(media_session_observer->IsPlaying(3));
-
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
-
- SystemResume();
-
- EXPECT_TRUE(media_session_observer->IsPlaying(0));
- EXPECT_TRUE(media_session_observer->IsPlaying(1));
- EXPECT_TRUE(media_session_observer->IsPlaying(2));
- EXPECT_TRUE(media_session_observer->IsPlaying(3));
-
- EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
- GetSessionAudioFocusType());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShowForContent) {
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- // Starting a player with a content type should show the media controls.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsNoShowForTransient) {
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, false, testing::_));
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- // Starting a player with a transient type should not show the media controls.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
-
- EXPECT_FALSE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsHideWhenStopped) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayers(media_session_observer.get());
-
- EXPECT_FALSE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShownAcceptTransient) {
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- // Transient player join the session without affecting the controls.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsShownAfterContentAdded) {
- Expectation dontShowControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_))
- .After(dontShowControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
-
- // The controls are shown when the content player is added.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsStayIfOnlyOnePlayerHasBeenPaused) {
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
-
- // Removing only content player doesn't hide the controls since the session
- // is still active.
- RemovePlayer(media_session_observer.get(), 0);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsHideWhenTheLastPlayerIsRemoved) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true, testing::_))
- .After(showControls);
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayer(media_session_observer.get(), 0);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-
- RemovePlayer(media_session_observer.get(), 1);
-
- EXPECT_FALSE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsHideWhenAllThePlayersAreRemoved) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- RemovePlayers(media_session_observer.get());
-
- EXPECT_FALSE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsNotHideWhenTheLastPlayerIsPaused) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- OnPlayerPaused(media_session_observer.get(), 0);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-
- OnPlayerPaused(media_session_observer.get(), 1);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- SuspendTemporaryUpdatesControls) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsUpdatedWhenResumed) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(true);
- SystemResume();
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsHideWhenSessionSuspendedPermanently) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(false);
-
- EXPECT_FALSE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ConstrolsHideWhenSessionStops) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- EXPECT_FALSE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsHideWhenSessionChangesFromContentToTransient) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, false, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(true);
-
- // This should reset the session and change it to a transient, so
- // hide the controls.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Transient);
-
- EXPECT_FALSE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsUpdatedWhenNewPlayerResetsSession) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(true);
-
- // This should reset the session and update the controls.
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsResumedWhenPlayerIsResumed) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(true);
-
- // This should resume the session and update the controls.
- AddPlayer(media_session_observer.get(), 0,
- media::MediaContentType::Persistent);
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsUpdatedDueToResumeSessionAction) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_))
- .After(showControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- UISuspend();
-
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- ControlsUpdatedDueToSuspendSessionAction) {
- Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_));
- Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true, testing::_)).After(showControls);
- EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false, testing::_))
- .After(pauseControls);
-
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- UISuspend();
- UIResume();
-
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- DontResumeBySystemUISuspendedSessions) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- UISuspend();
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-
- SystemResume();
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- AllowUIResumeForSystemSuspend) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-
- UIResume();
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromUI) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- UISuspend();
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-
- UIResume();
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromSystem) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- SystemSuspend(true);
- EXPECT_TRUE(IsControllable());
- EXPECT_TRUE(IsSuspended());
-
- SystemResume();
- EXPECT_TRUE(IsControllable());
- EXPECT_FALSE(IsSuspended());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_SystemTransient) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(true);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(0)); // System Transient
- EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(0, samples->GetCount(2)); // UI
-}
-
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_Suspended_SystemPermantent) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- SystemSuspend(false);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(0, samples->GetCount(0)); // System Transient
- EXPECT_EQ(1, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(0, samples->GetCount(2)); // UI
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_UI) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- UISuspend();
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(0, samples->GetCount(0)); // System Transient
- EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(1, samples->GetCount(2)); // UI
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Multiple) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- UISuspend();
- UIResume();
-
- SystemSuspend(true);
- SystemResume();
-
- UISuspend();
- UIResume();
-
- SystemSuspend(false);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(4, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(0)); // System Transient
- EXPECT_EQ(1, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(2, samples->GetCount(2)); // UI
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Crossing) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- UISuspend();
- SystemSuspend(true);
- SystemSuspend(false);
- UIResume();
-
- SystemSuspend(true);
- SystemSuspend(true);
- SystemSuspend(false);
- SystemResume();
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(0)); // System Transient
- EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(1, samples->GetCount(2)); // UI
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Stop) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(0, samples->GetCount(0)); // System Transient
- EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
- EXPECT_EQ(1, samples->GetCount(2)); // UI
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_ActiveTime_NoActivation) {
- base::HistogramTester tester;
-
- std::unique_ptr<MediaSession> media_session = CreateDummyMediaSession();
- media_session.reset();
-
- // A MediaSession that wasn't active doesn't register an active time.
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(0, samples->TotalCount());
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_SimpleActivation) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(1000));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_ActivationWithUISuspension) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- UISuspend();
-
- clock->Advance(base::TimeDelta::FromMilliseconds(2000));
- UIResume();
-
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(2000));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_ActivationWithSystemSuspension) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
-
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- SystemSuspend(true);
-
- clock->Advance(base::TimeDelta::FromMilliseconds(2000));
- SystemResume();
-
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(1, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(2000));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_ActivateSuspendedButNotStopped) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- clock->Advance(base::TimeDelta::FromMilliseconds(500));
- SystemSuspend(true);
-
- {
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(0, samples->TotalCount());
- }
-
- SystemResume();
- clock->Advance(base::TimeDelta::FromMilliseconds(5000));
- UISuspend();
-
- {
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(0, samples->TotalCount());
- }
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_ActivateSuspendStopTwice) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- clock->Advance(base::TimeDelta::FromMilliseconds(500));
- SystemSuspend(true);
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- clock->Advance(base::TimeDelta::FromMilliseconds(5000));
- SystemResume();
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(500));
- EXPECT_EQ(1, samples->GetCount(5000));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
- UMA_ActiveTime_MultipleActivations) {
- std::unique_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
- base::HistogramTester tester;
-
- MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
- base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
- clock->SetNowTicks(base::TimeTicks::Now());
- media_session_uma_helper->SetClockForTest(
- std::unique_ptr<base::SimpleTestTickClock>(clock));
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- clock->Advance(base::TimeDelta::FromMilliseconds(10000));
- RemovePlayer(media_session_observer.get(), 0);
-
- StartNewPlayer(media_session_observer.get(),
- media::MediaContentType::Persistent);
- clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
-
- std::unique_ptr<base::HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(1000));
- EXPECT_EQ(1, samples->GetCount(10000));
-}
diff --git a/chromium/content/browser/media/session/media_session_controller.cc b/chromium/content/browser/media/session/media_session_controller.cc
index 029e24da527..970bb4cb738 100644
--- a/chromium/content/browser/media/session/media_session_controller.cc
+++ b/chromium/content/browser/media/session/media_session_controller.cc
@@ -5,7 +5,7 @@
#include "content/browser/media/session/media_session_controller.h"
#include "content/browser/media/media_web_contents_observer.h"
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
@@ -19,7 +19,8 @@ MediaSessionController::MediaSessionController(
: id_(id),
media_web_contents_observer_(media_web_contents_observer),
media_session_(
- MediaSession::Get(media_web_contents_observer_->web_contents())) {}
+ MediaSessionImpl::Get(media_web_contents_observer_->web_contents())) {
+}
MediaSessionController::~MediaSessionController() {
if (!has_session_)
diff --git a/chromium/content/browser/media/session/media_session_controller.h b/chromium/content/browser/media/session/media_session_controller.h
index ce5af653e6b..f709828bd2b 100644
--- a/chromium/content/browser/media/session/media_session_controller.h
+++ b/chromium/content/browser/media/session/media_session_controller.h
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/time/time.h"
-#include "content/browser/media/session/media_session_observer.h"
+#include "content/browser/media/session/media_session_player_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
@@ -17,14 +17,14 @@ enum class MediaContentType;
namespace content {
-class MediaSession;
+class MediaSessionImpl;
class MediaWebContentsObserver;
// Helper class for controlling a single player's MediaSession instance. Sends
// browser side MediaSession commands back to a player hosted in the renderer
// process.
-class CONTENT_EXPORT MediaSessionController :
- NON_EXPORTED_BASE(public MediaSessionObserver) {
+class CONTENT_EXPORT MediaSessionController
+ : NON_EXPORTED_BASE(public MediaSessionPlayerObserver) {
public:
MediaSessionController(const WebContentsObserver::MediaPlayerId& id,
MediaWebContentsObserver* media_web_contents_observer);
@@ -61,7 +61,7 @@ class CONTENT_EXPORT MediaSessionController :
MediaWebContentsObserver* const media_web_contents_observer_;
// Non-owned pointer; lifetime is the same as |media_web_contents_observer_|.
- MediaSession* const media_session_;
+ MediaSessionImpl* const media_session_;
int player_id_ = 0;
bool has_session_ = false;
diff --git a/chromium/content/browser/media/session/media_session_controller_unittest.cc b/chromium/content/browser/media/session/media_session_controller_unittest.cc
index 88b721ead50..c2c2868ab12 100644
--- a/chromium/content/browser/media/session/media_session_controller_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controller_unittest.cc
@@ -5,8 +5,8 @@
#include <tuple>
#include "content/browser/media/media_web_contents_observer.h"
-#include "content/browser/media/session/media_session.h"
#include "content/browser/media/session/media_session_controller.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
@@ -35,7 +35,9 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
id_, contents()->media_web_contents_observer()));
}
- MediaSession* media_session() { return MediaSession::Get(contents()); }
+ MediaSessionImpl* media_session() {
+ return MediaSessionImpl::Get(contents());
+ }
IPC::TestSink& test_sink() { return main_test_rfh()->GetProcess()->sink(); }
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.cc b/chromium/content/browser/media/session/media_session_controllers_manager.cc
index f0cf9d43966..48f1377af65 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.cc
@@ -5,9 +5,7 @@
#include "content/browser/media/session/media_session_controllers_manager.h"
#include "base/command_line.h"
-#include "content/browser/media/session/media_session.h"
#include "content/browser/media/session/media_session_controller.h"
-#include "content/browser/media/session/media_session_observer.h"
#include "media/base/media_switches.h"
namespace content {
diff --git a/chromium/content/browser/media/session/media_session_delegate.h b/chromium/content/browser/media/session/media_session_delegate.h
deleted file mode 100644
index a0ed28b9ce4..00000000000
--- a/chromium/content/browser/media/session/media_session_delegate.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
-#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
-
-#include "content/browser/media/session/audio_focus_manager.h"
-#include "content/browser/media/session/media_session.h"
-
-namespace content {
-
-// MediaSessionDelegate is an interface abstracting audio focus handling for the
-// MediaSession class.
-class MediaSessionDelegate {
- public:
- // Factory method returning an implementation of MediaSessionDelegate.
- static std::unique_ptr<MediaSessionDelegate> Create(
- MediaSession* media_session);
-
- virtual ~MediaSessionDelegate() = default;
-
- virtual bool RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) = 0;
- virtual void AbandonAudioFocus() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
diff --git a/chromium/content/browser/media/session/media_session_delegate_android.cc b/chromium/content/browser/media/session/media_session_delegate_android.cc
deleted file mode 100644
index da826e9062a..00000000000
--- a/chromium/content/browser/media/session/media_session_delegate_android.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/session/media_session_delegate_android.h"
-
-#include "base/android/context_utils.h"
-#include "base/android/jni_android.h"
-#include "jni/MediaSessionDelegate_jni.h"
-
-using base::android::JavaParamRef;
-
-namespace content {
-
-// static
-bool MediaSessionDelegateAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-MediaSessionDelegateAndroid::MediaSessionDelegateAndroid(
- MediaSession* media_session)
- : media_session_(media_session) {
-}
-
-MediaSessionDelegateAndroid::~MediaSessionDelegateAndroid() {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- Java_MediaSessionDelegate_tearDown(env, j_media_session_delegate_);
-}
-
-void MediaSessionDelegateAndroid::Initialize() {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- j_media_session_delegate_.Reset(Java_MediaSessionDelegate_create(
- env,
- base::android::GetApplicationContext(),
- reinterpret_cast<intptr_t>(this)));
-}
-
-bool MediaSessionDelegateAndroid::RequestAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type) {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- return Java_MediaSessionDelegate_requestAudioFocus(
- env, j_media_session_delegate_,
- audio_focus_type ==
- AudioFocusManager::AudioFocusType::GainTransientMayDuck);
-}
-
-void MediaSessionDelegateAndroid::AbandonAudioFocus() {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- Java_MediaSessionDelegate_abandonAudioFocus(env, j_media_session_delegate_);
-}
-
-void MediaSessionDelegateAndroid::OnSuspend(
- JNIEnv*, const JavaParamRef<jobject>&, jboolean temporary) {
- // TODO(mlamouri): this check makes it so that if a MediaSession is paused and
- // then loses audio focus, it will still stay in the Suspended state.
- // See https://crbug.com/539998
- if (!media_session_->IsActive())
- return;
-
- if (temporary) {
- media_session_->Suspend(MediaSession::SuspendType::SYSTEM);
- } else {
- media_session_->Stop(MediaSession::SuspendType::SYSTEM);
- }
-}
-
-void MediaSessionDelegateAndroid::OnResume(
- JNIEnv*, const JavaParamRef<jobject>&) {
- if (!media_session_->IsReallySuspended())
- return;
-
- media_session_->Resume(MediaSession::SuspendType::SYSTEM);
-}
-
-void MediaSessionDelegateAndroid::OnStartDucking(JNIEnv*, jobject) {
- media_session_->StartDucking();
-}
-
-void MediaSessionDelegateAndroid::OnStopDucking(JNIEnv*, jobject) {
- media_session_->StopDucking();
-}
-
-void MediaSessionDelegateAndroid::RecordSessionDuck(
- JNIEnv*, const JavaParamRef<jobject>&) {
- media_session_->RecordSessionDuck();
-}
-
-// static
-std::unique_ptr<MediaSessionDelegate> MediaSessionDelegate::Create(
- MediaSession* media_session) {
- MediaSessionDelegateAndroid* delegate =
- new MediaSessionDelegateAndroid(media_session);
- delegate->Initialize();
- return std::unique_ptr<MediaSessionDelegate>(delegate);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/session/media_session.cc b/chromium/content/browser/media/session/media_session_impl.cc
index 147b3379af0..1b5e706c47a 100644
--- a/chromium/content/browser/media/session/media_session.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -2,15 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
-#include "content/browser/media/session/media_session_delegate.h"
-#include "content/browser/media/session/media_session_observer.h"
+#include <algorithm>
+#include "content/browser/media/session/audio_focus_delegate.h"
+#include "content/browser/media/session/media_session_player_observer.h"
+#include "content/browser/media/session/media_session_service_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/media_session.h"
+#include "content/public/browser/media_session_observer.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "media/base/media_content_type.h"
+#if defined(OS_ANDROID)
+#include "content/browser/media/session/media_session_android.h"
+#endif // defined(OS_ANDROID)
+
namespace content {
namespace {
@@ -23,22 +30,21 @@ const double kDuckingVolumeMultiplier = 0.2;
using MediaSessionSuspendedSource =
MediaSessionUmaHelper::MediaSessionSuspendedSource;
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSession);
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSessionImpl);
-MediaSession::PlayerIdentifier::PlayerIdentifier(MediaSessionObserver* observer,
- int player_id)
- : observer(observer),
- player_id(player_id) {
-}
+MediaSessionImpl::PlayerIdentifier::PlayerIdentifier(
+ MediaSessionPlayerObserver* observer,
+ int player_id)
+ : observer(observer), player_id(player_id) {}
-bool MediaSession::PlayerIdentifier::operator==(
+bool MediaSessionImpl::PlayerIdentifier::operator==(
const PlayerIdentifier& other) const {
return this->observer == other.observer && this->player_id == other.player_id;
}
-size_t MediaSession::PlayerIdentifier::Hash::operator()(
+size_t MediaSessionImpl::PlayerIdentifier::Hash::operator()(
const PlayerIdentifier& player_identifier) const {
- size_t hash = BASE_HASH_NAMESPACE::hash<MediaSessionObserver*>()(
+ size_t hash = BASE_HASH_NAMESPACE::hash<MediaSessionPlayerObserver*>()(
player_identifier.observer);
hash += BASE_HASH_NAMESPACE::hash<int>()(player_identifier.player_id);
return hash;
@@ -46,7 +52,12 @@ size_t MediaSession::PlayerIdentifier::Hash::operator()(
// static
MediaSession* MediaSession::Get(WebContents* web_contents) {
- MediaSession* session = FromWebContents(web_contents);
+ return MediaSessionImpl::Get(web_contents);
+}
+
+// static
+MediaSessionImpl* MediaSessionImpl::Get(WebContents* web_contents) {
+ MediaSessionImpl* session = FromWebContents(web_contents);
if (!session) {
CreateForWebContents(web_contents);
session = FromWebContents(web_contents);
@@ -55,43 +66,59 @@ MediaSession* MediaSession::Get(WebContents* web_contents) {
return session;
}
-MediaSession::~MediaSession() {
- DCHECK(players_.empty());
+MediaSessionImpl::~MediaSessionImpl() {
+ DCHECK(normal_players_.empty());
+ DCHECK(pepper_players_.empty());
+ DCHECK(one_shot_players_.empty());
DCHECK(audio_focus_state_ == State::INACTIVE);
+ for (auto& observer : observers_)
+ observer.MediaSessionDestroyed();
}
-void MediaSession::WebContentsDestroyed() {
+void MediaSessionImpl::WebContentsDestroyed() {
// This should only work for tests. In production, all the players should have
// already been removed before WebContents is destroyed.
- // TODO(zqzhang): refactor MediaSession, maybe move the interface used to talk
- // with AudioFocusManager out to a seperate class. The AudioFocusManager unit
- // tests then could mock the interface and abandon audio focus when
+ // TODO(zqzhang): refactor MediaSessionImpl, maybe move the interface used to
+ // talk with AudioFocusManager out to a seperate class. The AudioFocusManager
+ // unit tests then could mock the interface and abandon audio focus when
// WebContents is destroyed. See https://crbug.com/651069
- players_.clear();
+ normal_players_.clear();
pepper_players_.clear();
+ one_shot_players_.clear();
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSession::SetMetadata(const base::Optional<MediaMetadata>& metadata) {
+void MediaSessionImpl::SetMediaSessionService(
+ MediaSessionServiceImpl* service) {
+ service_ = service;
+}
+
+void MediaSessionImpl::AddObserver(MediaSessionObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void MediaSessionImpl::RemoveObserver(MediaSessionObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void MediaSessionImpl::SetMetadata(
+ const base::Optional<MediaMetadata>& metadata) {
metadata_ = metadata;
- // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the
- // media session play/pause state changes. Need to find a way to seprate the
- // state change and Metadata update. See https://crbug.com/621855.
- static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
+ for (auto& observer : observers_)
+ observer.MediaSessionMetadataChanged(metadata);
}
-bool MediaSession::AddPlayer(MediaSessionObserver* observer,
- int player_id,
- media::MediaContentType media_content_type) {
+bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
+ int player_id,
+ media::MediaContentType media_content_type) {
+ if (media_content_type == media::MediaContentType::OneShot)
+ return AddOneShotPlayer(observer, player_id);
if (media_content_type == media::MediaContentType::Pepper)
return AddPepperPlayer(observer, player_id);
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
- // Determine the audio focus type required for playing the new player.
- // TODO(zqzhang): handle duckable and uncontrollable.
- // See https://crbug.com/639277.
AudioFocusManager::AudioFocusType required_audio_focus_type;
if (media_content_type == media::MediaContentType::Persistent) {
required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
@@ -107,7 +134,7 @@ bool MediaSession::AddPlayer(MediaSessionObserver* observer,
if (audio_focus_state_ == State::ACTIVE &&
(audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain ||
audio_focus_type_ == required_audio_focus_type)) {
- players_.insert(PlayerIdentifier(observer, player_id));
+ normal_players_.insert(PlayerIdentifier(observer, player_id));
return true;
}
@@ -120,62 +147,103 @@ bool MediaSession::AddPlayer(MediaSessionObserver* observer,
// The session should be reset if a player is starting while all players are
// suspended.
if (old_audio_focus_state != State::ACTIVE)
- players_.clear();
+ normal_players_.clear();
- players_.insert(PlayerIdentifier(observer, player_id));
- UpdateWebContents();
+ normal_players_.insert(PlayerIdentifier(observer, player_id));
+ NotifyAboutStateChange();
return true;
}
-void MediaSession::RemovePlayer(MediaSessionObserver* observer,
- int player_id) {
- auto it = players_.find(PlayerIdentifier(observer, player_id));
- if (it != players_.end())
- players_.erase(it);
+void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
+ int player_id) {
+ bool was_controllable = IsControllable();
- it = pepper_players_.find(PlayerIdentifier(observer, player_id));
+ PlayerIdentifier identifier(observer, player_id);
+
+ auto it = normal_players_.find(identifier);
+ if (it != normal_players_.end())
+ normal_players_.erase(it);
+
+ it = pepper_players_.find(identifier);
if (it != pepper_players_.end())
pepper_players_.erase(it);
+ it = one_shot_players_.find(identifier);
+ if (it != one_shot_players_.end())
+ one_shot_players_.erase(it);
+
AbandonSystemAudioFocusIfNeeded();
+
+ // The session may become controllable after removing a one-shot player.
+ // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
+ // about the state change.
+ if (!was_controllable && IsControllable())
+ NotifyAboutStateChange();
}
-void MediaSession::RemovePlayers(MediaSessionObserver* observer) {
- for (auto it = players_.begin(); it != players_.end(); ) {
+void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
+ bool was_controllable = IsControllable();
+
+ for (auto it = normal_players_.begin(); it != normal_players_.end();) {
if (it->observer == observer)
- players_.erase(it++);
+ normal_players_.erase(it++);
else
++it;
}
- for (auto it = pepper_players_.begin(); it != pepper_players_.end(); ) {
+ for (auto it = pepper_players_.begin(); it != pepper_players_.end();) {
if (it->observer == observer)
pepper_players_.erase(it++);
else
++it;
}
+ for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) {
+ if (it->observer == observer)
+ one_shot_players_.erase(it++);
+ else
+ ++it;
+ }
+
AbandonSystemAudioFocusIfNeeded();
+
+ // The session may become controllable after removing a one-shot player.
+ // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
+ // about the state change.
+ if (!was_controllable && IsControllable())
+ NotifyAboutStateChange();
}
-void MediaSession::RecordSessionDuck() {
+void MediaSessionImpl::RecordSessionDuck() {
uma_helper_.RecordSessionSuspended(
MediaSessionSuspendedSource::SystemTransientDuck);
}
-void MediaSession::OnPlayerPaused(MediaSessionObserver* observer,
- int player_id) {
+void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer,
+ int player_id) {
// If a playback is completed, BrowserMediaPlayerManager will call
// OnPlayerPaused() after RemovePlayer(). This is a workaround.
// Also, this method may be called when a player that is not added
- // to this session (e.g. a silent video) is paused. MediaSession
+ // to this session (e.g. a silent video) is paused. MediaSessionImpl
// should ignore the paused player for this case.
- if (!players_.count(PlayerIdentifier(observer, player_id)))
+ PlayerIdentifier identifier(observer, player_id);
+ if (!normal_players_.count(identifier) &&
+ !pepper_players_.count(identifier) &&
+ !one_shot_players_.count(identifier)) {
+ return;
+ }
+
+ // If the player to be removed is a pepper player, or there is more than one
+ // observer, remove the paused one from the session.
+ if (pepper_players_.count(identifier) || normal_players_.size() != 1) {
+ RemovePlayer(observer, player_id);
return;
+ }
- // If there is more than one observer, remove the paused one from the session.
- if (players_.size() != 1) {
+ // If the player is a one-shot player, just remove it since it is not expected
+ // to resume a one-shot player via resuming MediaSession.
+ if (one_shot_players_.count(identifier)) {
RemovePlayer(observer, player_id);
return;
}
@@ -185,7 +253,7 @@ void MediaSession::OnPlayerPaused(MediaSessionObserver* observer,
OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
}
-void MediaSession::Resume(SuspendType suspend_type) {
+void MediaSessionImpl::Resume(SuspendType suspend_type) {
DCHECK(IsReallySuspended());
// When the resume requests comes from another source than system, audio focus
@@ -205,13 +273,13 @@ void MediaSession::Resume(SuspendType suspend_type) {
OnResumeInternal(suspend_type);
}
-void MediaSession::Suspend(SuspendType suspend_type) {
+void MediaSessionImpl::Suspend(SuspendType suspend_type) {
DCHECK(!IsSuspended());
OnSuspendInternal(suspend_type, State::SUSPENDED);
}
-void MediaSession::Stop(SuspendType suspend_type) {
+void MediaSessionImpl::Stop(SuspendType suspend_type) {
DCHECK(audio_focus_state_ != State::INACTIVE);
DCHECK(suspend_type != SuspendType::CONTENT);
DCHECK(!HasPepper());
@@ -226,92 +294,117 @@ void MediaSession::Stop(SuspendType suspend_type) {
OnSuspendInternal(suspend_type, State::SUSPENDED);
DCHECK(audio_focus_state_ == State::SUSPENDED);
- players_.clear();
+ normal_players_.clear();
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSession::StartDucking() {
+void MediaSessionImpl::DidReceiveAction(
+ blink::mojom::MediaSessionAction action) {
+ if (service_)
+ service_->GetClient()->DidReceiveAction(action);
+}
+
+void MediaSessionImpl::OnMediaSessionEnabledAction(
+ blink::mojom::MediaSessionAction action) {
+ for (auto& observer : observers_)
+ observer.MediaSessionEnabledAction(action);
+}
+
+void MediaSessionImpl::OnMediaSessionDisabledAction(
+ blink::mojom::MediaSessionAction action) {
+ for (auto& observer : observers_)
+ observer.MediaSessionDisabledAction(action);
+}
+
+void MediaSessionImpl::StartDucking() {
if (is_ducking_)
return;
is_ducking_ = true;
UpdateVolumeMultiplier();
}
-void MediaSession::StopDucking() {
+void MediaSessionImpl::StopDucking() {
if (!is_ducking_)
return;
is_ducking_ = false;
UpdateVolumeMultiplier();
}
-void MediaSession::UpdateVolumeMultiplier() {
- for (const auto& it : players_)
+void MediaSessionImpl::UpdateVolumeMultiplier() {
+ for (const auto& it : normal_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
}
-double MediaSession::GetVolumeMultiplier() const {
+double MediaSessionImpl::GetVolumeMultiplier() const {
return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier;
}
-bool MediaSession::IsActive() const {
+bool MediaSessionImpl::IsActive() const {
return audio_focus_state_ == State::ACTIVE;
}
-bool MediaSession::IsReallySuspended() const {
+bool MediaSessionImpl::IsReallySuspended() const {
return audio_focus_state_ == State::SUSPENDED;
}
-bool MediaSession::IsSuspended() const {
+bool MediaSessionImpl::IsSuspended() const {
// TODO(mlamouri): should be == State::SUSPENDED.
return audio_focus_state_ != State::ACTIVE;
}
-bool MediaSession::IsControllable() const {
+bool MediaSessionImpl::IsControllable() const {
// Only media session having focus Gain can be controllable unless it is
- // inactive.
+ // 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;
+ audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
+ one_shot_players_.empty();
}
-bool MediaSession::HasPepper() const {
+bool MediaSessionImpl::HasPepper() const {
return !pepper_players_.empty();
}
-std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
-MediaSession::RegisterMediaSessionStateChangedCallbackForTest(
+std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription>
+MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest(
const StateChangedCallback& cb) {
return media_session_state_listeners_.Add(cb);
}
-void MediaSession::SetDelegateForTests(
- std::unique_ptr<MediaSessionDelegate> delegate) {
+void MediaSessionImpl::SetDelegateForTests(
+ std::unique_ptr<AudioFocusDelegate> delegate) {
delegate_ = std::move(delegate);
}
-bool MediaSession::IsActiveForTest() const {
+bool MediaSessionImpl::IsActiveForTest() const {
return audio_focus_state_ == State::ACTIVE;
}
-MediaSessionUmaHelper* MediaSession::uma_helper_for_test() {
+MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() {
return &uma_helper_;
}
-void MediaSession::RemoveAllPlayersForTest() {
- players_.clear();
+void MediaSessionImpl::RemoveAllPlayersForTest() {
+ normal_players_.clear();
+ pepper_players_.clear();
+ one_shot_players_.clear();
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSession::OnSuspendInternal(SuspendType suspend_type,
- State new_state) {
+void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
+ State new_state) {
DCHECK(!HasPepper());
DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE);
// UI suspend cannot use State::INACTIVE.
DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
+ if (!one_shot_players_.empty())
+ return;
+
if (audio_focus_state_ != State::ACTIVE)
return;
@@ -346,71 +439,77 @@ void MediaSession::OnSuspendInternal(SuspendType suspend_type,
// SuspendType::CONTENT happens when the suspend action came from
// the page in which case the player is already paused.
// Otherwise, the players need to be paused.
- for (const auto& it : players_)
+ for (const auto& it : normal_players_)
it.observer->OnSuspend(it.player_id);
}
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier);
- UpdateWebContents();
+ NotifyAboutStateChange();
}
-void MediaSession::OnResumeInternal(SuspendType suspend_type) {
+void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type)
return;
SetAudioFocusState(State::ACTIVE);
- for (const auto& it : players_)
+ for (const auto& it : normal_players_)
it.observer->OnResume(it.player_id);
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
- UpdateWebContents();
+ NotifyAboutStateChange();
}
-MediaSession::MediaSession(WebContents* web_contents)
+MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
: WebContentsObserver(web_contents),
audio_focus_state_(State::INACTIVE),
audio_focus_type_(
AudioFocusManager::AudioFocusType::GainTransientMayDuck),
- is_ducking_(false) {}
+ is_ducking_(false),
+ service_(nullptr) {
+#if defined(OS_ANDROID)
+ session_android_.reset(new MediaSessionAndroid(this));
+#endif // defined(OS_ANDROID)
+}
-void MediaSession::Initialize() {
- delegate_ = MediaSessionDelegate::Create(this);
+void MediaSessionImpl::Initialize() {
+ delegate_ = AudioFocusDelegate::Create(this);
}
-bool MediaSession::RequestSystemAudioFocus(
+bool MediaSessionImpl::RequestSystemAudioFocus(
AudioFocusManager::AudioFocusType audio_focus_type) {
bool result = delegate_->RequestAudioFocus(audio_focus_type);
uma_helper_.RecordRequestAudioFocusResult(result);
- // MediaSession must change its state & audio focus type AFTER requesting
+ // MediaSessionImpl must change its state & audio focus type AFTER requesting
// audio focus.
SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
audio_focus_type_ = audio_focus_type;
return result;
}
-void MediaSession::AbandonSystemAudioFocusIfNeeded() {
- if (audio_focus_state_ == State::INACTIVE || !players_.empty() ||
- !pepper_players_.empty()) {
+void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
+ if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
+ !pepper_players_.empty() || !one_shot_players_.empty()) {
return;
}
delegate_->AbandonAudioFocus();
SetAudioFocusState(State::INACTIVE);
- UpdateWebContents();
+ NotifyAboutStateChange();
}
-void MediaSession::UpdateWebContents() {
+void MediaSessionImpl::NotifyAboutStateChange() {
media_session_state_listeners_.Notify(audio_focus_state_);
- static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
+ for (auto& observer : observers_)
+ observer.MediaSessionStateChanged(IsControllable(), IsSuspended());
}
-void MediaSession::SetAudioFocusState(State audio_focus_state) {
+void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) {
if (audio_focus_state == audio_focus_state_)
return;
@@ -428,16 +527,28 @@ void MediaSession::SetAudioFocusState(State audio_focus_state) {
}
}
-bool MediaSession::AddPepperPlayer(MediaSessionObserver* observer,
- int player_id) {
- bool success = RequestSystemAudioFocus(
- AudioFocusManager::AudioFocusType::Gain);
+bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
+ int player_id) {
+ bool success =
+ RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
DCHECK(success);
pepper_players_.insert(PlayerIdentifier(observer, player_id));
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
+ NotifyAboutStateChange();
+ return success;
+}
+
+bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
+ int player_id) {
+ if (!RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain))
+ return false;
+
+ one_shot_players_.insert(PlayerIdentifier(observer, player_id));
+ NotifyAboutStateChange();
+
return true;
}
diff --git a/chromium/content/browser/media/session/media_session.h b/chromium/content/browser/media/session/media_session_impl.h
index ba8f9995df9..1f1a0fc85d1 100644
--- a/chromium/content/browser/media/session/media_session.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -2,23 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
-#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_IMPL_H_
#include <stddef.h>
#include "base/callback_list.h"
#include "base/id_map.h"
#include "base/macros.h"
+#include "base/observer_list.h"
#include "base/optional.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_uma_helper.h"
#include "content/common/content_export.h"
+#include "content/public/browser/media_session.h"
+#include "content/public/browser/media_session_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/media_metadata.h"
-class MediaSessionBrowserTest;
+#if defined(OS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#endif // defined(OS_ANDROID)
+
+class MediaSessionImplBrowserTest;
namespace media {
enum class MediaContentType;
@@ -26,50 +33,56 @@ enum class MediaContentType;
namespace content {
+class AudioFocusDelegate;
class AudioFocusManagerTest;
-class MediaSessionDelegate;
+class MediaSessionImplStateObserver;
+class MediaSessionImplVisibilityBrowserTest;
class MediaSessionObserver;
-class MediaSessionStateObserver;
-class MediaSessionVisibilityBrowserTest;
+class MediaSessionPlayerObserver;
+class MediaSessionServiceImpl;
+
+#if defined(OS_ANDROID)
+class MediaSessionAndroid;
+#endif // defined(OS_ANDROID)
-// MediaSession manages the media session and audio focus for a given
-// WebContents. It is requesting the audio focus, pausing when requested by the
-// system and dropping it on demand.
-// The audio focus can be of two types: Transient or Content. A Transient audio
+// MediaSessionImpl is the implementation of MediaSession. It manages the media
+// session and audio focus for a given WebContents. It is requesting the audio
+// focus, pausing when requested by the system and dropping it on demand. The
+// audio focus can be of two types: Transient or Content. A Transient audio
// focus will allow other players to duck instead of pausing and will be
// declared as temporary to the system. A Content audio focus will not be
// declared as temporary and will not allow other players to duck. If a given
// WebContents can only have one audio focus at a time, it will be Content in
// case of Transient and Content audio focus are both requested.
-// TODO(thakis,mlamouri): MediaSession isn't CONTENT_EXPORT'd because it creates
-// complicated build issues with WebContentsUserData being a non-exported
-// template, see htttps://crbug.com/589840. As a result, the class uses
-// CONTENT_EXPORT for methods that are being used from tests. CONTENT_EXPORT
-// should be moved back to the class when the Windows build will work with it.
-class MediaSession : public WebContentsObserver,
- protected WebContentsUserData<MediaSession> {
+// TODO(thakis,mlamouri): MediaSessionImpl isn't CONTENT_EXPORT'd because it
+// creates complicated build issues with WebContentsUserData being a
+// non-exported template, see https://crbug.com/589840. As a result, the class
+// uses CONTENT_EXPORT for methods that are being used from tests.
+// CONTENT_EXPORT should be moved back to the class when the Windows build will
+// work with it.
+class MediaSessionImpl : public MediaSession,
+ public WebContentsObserver,
+ protected WebContentsUserData<MediaSessionImpl> {
public:
- enum class SuspendType {
- // Suspended by the system because a transient sound needs to be played.
- SYSTEM,
- // Suspended by the UI.
- UI,
- // Suspended by the page via script or user interaction.
- CONTENT,
- };
-
// Only visible to tests.
- enum class State {
- ACTIVE,
- SUSPENDED,
- INACTIVE
- };
+ enum class State { ACTIVE, SUSPENDED, INACTIVE };
- // Returns the MediaSession associated to this WebContents. Creates one if
+ // Returns the MediaSessionImpl associated to this WebContents. Creates one if
// none is currently available.
- CONTENT_EXPORT static MediaSession* Get(WebContents* web_contents);
+ CONTENT_EXPORT static MediaSessionImpl* Get(WebContents* web_contents);
+
+ ~MediaSessionImpl() override;
+
+#if defined(OS_ANDROID)
+ static MediaSession* FromJavaMediaSession(
+ const base::android::JavaRef<jobject>& j_media_session);
+ MediaSessionAndroid* session_android() const {
+ return session_android_.get();
+ }
+#endif // defined(OS_ANDROID)
- ~MediaSession() override;
+ void AddObserver(MediaSessionObserver* observer);
+ void RemoveObserver(MediaSessionObserver* observer);
void SetMetadata(const base::Optional<MediaMetadata>& metadata);
const base::Optional<MediaMetadata>& metadata() const { return metadata_; }
@@ -77,18 +90,18 @@ class MediaSession : public WebContentsObserver,
// Adds the given player to the current media session. Returns whether the
// player was successfully added. If it returns false, AddPlayer() should be
// called again later.
- CONTENT_EXPORT bool AddPlayer(MediaSessionObserver* observer,
+ CONTENT_EXPORT bool AddPlayer(MediaSessionPlayerObserver* observer,
int player_id,
media::MediaContentType media_content_type);
// Removes the given player from the current media session. Abandons audio
// focus if that was the last player in the session.
- CONTENT_EXPORT void RemovePlayer(MediaSessionObserver* observer,
+ CONTENT_EXPORT void RemovePlayer(MediaSessionPlayerObserver* observer,
int player_id);
// Removes all the players associated with |observer|. Abandons audio focus if
// these were the last players in the session.
- CONTENT_EXPORT void RemovePlayers(MediaSessionObserver* observer);
+ CONTENT_EXPORT void RemovePlayers(MediaSessionPlayerObserver* observer);
// Record that the session was ducked.
void RecordSessionDuck();
@@ -96,20 +109,31 @@ class MediaSession : public WebContentsObserver,
// Called when a player is paused in the content.
// If the paused player is the last player, we suspend the MediaSession.
// Otherwise, the paused player will be removed from the MediaSession.
- CONTENT_EXPORT void OnPlayerPaused(MediaSessionObserver* observer,
+ CONTENT_EXPORT void OnPlayerPaused(MediaSessionPlayerObserver* observer,
int player_id);
// Resume the media session.
// |type| represents the origin of the request.
- CONTENT_EXPORT void Resume(SuspendType suspend_type);
+ CONTENT_EXPORT void Resume(MediaSession::SuspendType suspend_type) override;
// Suspend the media session.
// |type| represents the origin of the request.
- CONTENT_EXPORT void Suspend(SuspendType suspend_type);
+ CONTENT_EXPORT void Suspend(MediaSession::SuspendType suspend_type) override;
// Stop the media session.
// |type| represents the origin of the request.
- CONTENT_EXPORT void Stop(SuspendType suspend_type);
+ CONTENT_EXPORT void Stop(MediaSession::SuspendType suspend_type) override;
+
+ // Received a media session action and forward to blink::MediaSession.
+ void DidReceiveAction(blink::mojom::MediaSessionAction action) override;
+
+ // Called when an action is enabled in blink::MediaSession. This method will
+ // notify the observers that the action is enabled.
+ void OnMediaSessionEnabledAction(blink::mojom::MediaSessionAction action);
+
+ // Called when an action is disabled in blink::MediaSession. This method will
+ // notify the observers that the action is disabled.
+ void OnMediaSessionDisabledAction(blink::mojom::MediaSessionAction action);
// Let the media session start ducking such that the volume multiplier is
// reduced.
@@ -148,22 +172,27 @@ class MediaSession : public WebContentsObserver,
// WebContentsObserver implementation
void WebContentsDestroyed() override;
+ // Sets the associated MediaSessionService for communicating with
+ // blink::MediaSession.
+ MediaSessionServiceImpl* GetMediaSessionService() { return service_; }
+ void SetMediaSessionService(MediaSessionServiceImpl* service);
+
private:
- friend class content::WebContentsUserData<MediaSession>;
- friend class ::MediaSessionBrowserTest;
- friend class content::MediaSessionVisibilityBrowserTest;
+ friend class content::WebContentsUserData<MediaSessionImpl>;
+ friend class ::MediaSessionImplBrowserTest;
+ friend class content::MediaSessionImplVisibilityBrowserTest;
friend class content::AudioFocusManagerTest;
- friend class content::MediaSessionStateObserver;
+ friend class content::MediaSessionImplStateObserver;
CONTENT_EXPORT void SetDelegateForTests(
- std::unique_ptr<MediaSessionDelegate> delegate);
+ std::unique_ptr<AudioFocusDelegate> delegate);
CONTENT_EXPORT bool IsActiveForTest() const;
CONTENT_EXPORT void RemoveAllPlayersForTest();
CONTENT_EXPORT MediaSessionUmaHelper* uma_helper_for_test();
- // Representation of a player for the MediaSession.
+ // Representation of a player for the MediaSessionImpl.
struct PlayerIdentifier {
- PlayerIdentifier(MediaSessionObserver* observer, int player_id);
+ PlayerIdentifier(MediaSessionPlayerObserver* observer, int player_id);
PlayerIdentifier(const PlayerIdentifier&) = default;
void operator=(const PlayerIdentifier&) = delete;
@@ -174,21 +203,21 @@ class MediaSession : public WebContentsObserver,
size_t operator()(const PlayerIdentifier& player_identifier) const;
};
- MediaSessionObserver* observer;
+ MediaSessionPlayerObserver* observer;
int player_id;
};
using PlayersMap = base::hash_set<PlayerIdentifier, PlayerIdentifier::Hash>;
using StateChangedCallback = base::Callback<void(State)>;
- CONTENT_EXPORT explicit MediaSession(WebContents* web_contents);
+ CONTENT_EXPORT explicit MediaSessionImpl(WebContents* web_contents);
void Initialize();
- CONTENT_EXPORT void OnSuspendInternal(SuspendType suspend_type,
+ CONTENT_EXPORT void OnSuspendInternal(MediaSession::SuspendType suspend_type,
State new_state);
- CONTENT_EXPORT void OnResumeInternal(SuspendType suspend_type);
+ CONTENT_EXPORT void OnResumeInternal(MediaSession::SuspendType suspend_type);
- // Requests audio focus to the MediaSessionDelegate.
+ // Requests audio focus to the AudioFocusDelegate.
// Returns whether the request was granted.
CONTENT_EXPORT bool RequestSystemAudioFocus(
AudioFocusManager::AudioFocusType audio_focus_type);
@@ -197,8 +226,8 @@ class MediaSession : public WebContentsObserver,
// delegate to abandon the audio focus.
CONTENT_EXPORT void AbandonSystemAudioFocusIfNeeded();
- // Notifies WebContents about the state change of the media session.
- void UpdateWebContents();
+ // Notifies observers about the state change of the media session.
+ void NotifyAboutStateChange();
// Internal method that should be used instead of setting audio_focus_state_.
// It sets audio_focus_state_ and notifies observers about the state change.
@@ -211,20 +240,24 @@ class MediaSession : public WebContentsObserver,
// ducking.
double GetVolumeMultiplier() const;
- // Registers a MediaSession state change callback.
+ // Registers a MediaSessionImpl state change callback.
CONTENT_EXPORT std::unique_ptr<base::CallbackList<void(State)>::Subscription>
RegisterMediaSessionStateChangedCallbackForTest(
const StateChangedCallback& cb);
- CONTENT_EXPORT bool AddPepperPlayer(MediaSessionObserver* observer,
+ CONTENT_EXPORT bool AddPepperPlayer(MediaSessionPlayerObserver* observer,
int player_id);
- std::unique_ptr<MediaSessionDelegate> delegate_;
- PlayersMap players_;
+ CONTENT_EXPORT bool AddOneShotPlayer(MediaSessionPlayerObserver* observer,
+ int player_id);
+
+ std::unique_ptr<AudioFocusDelegate> delegate_;
+ PlayersMap normal_players_;
PlayersMap pepper_players_;
+ PlayersMap one_shot_players_;
State audio_focus_state_;
- SuspendType suspend_type_;
+ MediaSession::SuspendType suspend_type_;
AudioFocusManager::AudioFocusType audio_focus_type_;
MediaSessionUmaHelper uma_helper_;
@@ -237,9 +270,19 @@ class MediaSession : public WebContentsObserver,
base::Optional<MediaMetadata> metadata_;
base::CallbackList<void(State)> media_session_state_listeners_;
- DISALLOW_COPY_AND_ASSIGN(MediaSession);
+ base::ObserverList<MediaSessionObserver> observers_;
+
+#if defined(OS_ANDROID)
+ std::unique_ptr<MediaSessionAndroid> session_android_;
+#endif // defined(OS_ANDROID)
+
+ // The MediaSessionService this session is associated with (the service of the
+ // top-level frame).
+ MediaSessionServiceImpl* service_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_IMPL_H_
diff --git a/chromium/content/browser/media/session/media_session_impl_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
new file mode 100644
index 00000000000..c9ecbb30fd1
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -0,0 +1,1316 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_impl.h"
+
+#include <stddef.h>
+
+#include <list>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "content/browser/media/session/audio_focus_delegate.h"
+#include "content/browser/media/session/mock_media_session_player_observer.h"
+#include "content/public/browser/media_session.h"
+#include "content/public/browser/media_session_observer.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/media_content_type.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using content::WebContents;
+using content::MediaSession;
+using content::MediaSessionImpl;
+using content::MediaSessionObserver;
+using content::AudioFocusDelegate;
+using content::MediaSessionPlayerObserver;
+using content::MediaSessionUmaHelper;
+using content::MockMediaSessionPlayerObserver;
+
+using ::testing::Expectation;
+using ::testing::_;
+
+namespace {
+
+const double kDefaultVolumeMultiplier = 1.0;
+const double kDuckingVolumeMultiplier = 0.2;
+
+class MockAudioFocusDelegate : public AudioFocusDelegate {
+ public:
+ MockAudioFocusDelegate() {
+ ON_CALL(*this, RequestAudioFocus(_)).WillByDefault(::testing::Return(true));
+ }
+
+ MOCK_METHOD1(RequestAudioFocus,
+ bool(content::AudioFocusManager::AudioFocusType));
+ MOCK_METHOD0(AbandonAudioFocus, void());
+};
+
+class MockMediaSessionObserver : public MediaSessionObserver {
+ public:
+ MockMediaSessionObserver(MediaSession* media_session)
+ : MediaSessionObserver(media_session) {}
+
+ MOCK_METHOD2(MediaSessionStateChanged,
+ void(bool is_controllable, bool is_suspended));
+ MOCK_METHOD0(MediaSessionDestroyed, void());
+};
+
+} // namespace
+
+class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
+ protected:
+ MediaSessionImplBrowserTest() = default;
+
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ media_session_ = MediaSessionImpl::Get(shell()->web_contents());
+ mock_media_session_observer_.reset(
+ new MockMediaSessionObserver(media_session_));
+ mock_audio_focus_delegate_ = new MockAudioFocusDelegate;
+ media_session_->SetDelegateForTests(
+ base::WrapUnique(mock_audio_focus_delegate_));
+ ASSERT_TRUE(media_session_);
+ }
+
+ void TearDownOnMainThread() override {
+ mock_media_session_observer_.reset();
+
+ media_session_->RemoveAllPlayersForTest();
+ media_session_ = nullptr;
+
+ ContentBrowserTest::TearDownOnMainThread();
+ }
+
+ void StartNewPlayer(MockMediaSessionPlayerObserver* player_observer,
+ media::MediaContentType media_content_type) {
+ bool result = AddPlayer(player_observer, player_observer->StartNewPlayer(),
+ media_content_type);
+ EXPECT_TRUE(result);
+ }
+
+ bool AddPlayer(MockMediaSessionPlayerObserver* player_observer,
+ int player_id,
+ media::MediaContentType type) {
+ return media_session_->AddPlayer(player_observer, player_id, type);
+ }
+
+ void RemovePlayer(MockMediaSessionPlayerObserver* player_observer,
+ int player_id) {
+ media_session_->RemovePlayer(player_observer, player_id);
+ }
+
+ void RemovePlayers(MockMediaSessionPlayerObserver* player_observer) {
+ media_session_->RemovePlayers(player_observer);
+ }
+
+ void OnPlayerPaused(MockMediaSessionPlayerObserver* player_observer,
+ int player_id) {
+ media_session_->OnPlayerPaused(player_observer, player_id);
+ }
+
+ bool HasAudioFocus() { return media_session_->IsActiveForTest(); }
+
+ content::AudioFocusManager::AudioFocusType GetSessionAudioFocusType() {
+ return media_session_->audio_focus_type();
+ }
+
+ bool IsControllable() { return media_session_->IsControllable(); }
+
+ bool IsSuspended() { return media_session_->IsSuspended(); }
+
+ void UIResume() { media_session_->Resume(MediaSession::SuspendType::UI); }
+
+ void SystemResume() {
+ media_session_->OnResumeInternal(MediaSession::SuspendType::SYSTEM);
+ }
+
+ void UISuspend() { media_session_->Suspend(MediaSession::SuspendType::UI); }
+
+ void SystemSuspend(bool temporary) {
+ media_session_->OnSuspendInternal(MediaSession::SuspendType::SYSTEM,
+ temporary
+ ? MediaSessionImpl::State::SUSPENDED
+ : MediaSessionImpl::State::INACTIVE);
+ }
+
+ void SystemStartDucking() { media_session_->StartDucking(); }
+
+ void SystemStopDucking() { media_session_->StopDucking(); }
+
+ MockMediaSessionObserver* mock_media_session_observer() {
+ return mock_media_session_observer_.get();
+ }
+
+ MockAudioFocusDelegate* mock_audio_focus_delegate() {
+ return mock_audio_focus_delegate_;
+ }
+
+ std::unique_ptr<MediaSessionImpl> CreateDummyMediaSession() {
+ return base::WrapUnique<MediaSessionImpl>(new MediaSessionImpl(nullptr));
+ }
+
+ MediaSessionUmaHelper* GetMediaSessionUMAHelper() {
+ return media_session_->uma_helper_for_test();
+ }
+
+ protected:
+ MediaSessionImpl* media_session_;
+ std::unique_ptr<MockMediaSessionObserver> mock_media_session_observer_;
+ MockAudioFocusDelegate* mock_audio_focus_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionImplBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ PlayersFromSameObserverDoNotStopEachOtherInSameSession) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(player_observer->IsPlaying(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ PlayersFromManyObserverDoNotStopEachOtherInSameSession) {
+ auto player_observer_1 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ auto player_observer_2 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ auto player_observer_3 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_3.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(player_observer_1->IsPlaying(0));
+ EXPECT_TRUE(player_observer_2->IsPlaying(0));
+ EXPECT_TRUE(player_observer_3->IsPlaying(0));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ SuspendedMediaSessionStopsPlayers) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+ EXPECT_FALSE(player_observer->IsPlaying(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ResumedMediaSessionRestartsPlayers) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+ SystemResume();
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(player_observer->IsPlaying(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ StartedPlayerOnSuspendedSessionPlaysAlone) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ SystemSuspend(true);
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(player_observer->IsPlaying(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, InitialVolumeMultiplier) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ StartDuckingReducesVolumeMultiplier) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemStartDucking();
+
+ EXPECT_EQ(kDuckingVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+ EXPECT_EQ(kDuckingVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_EQ(kDuckingVolumeMultiplier, player_observer->GetVolumeMultiplier(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ StopDuckingRecoversVolumeMultiplier) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemStartDucking();
+ SystemStopDucking();
+
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(2));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusInitialState) {
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, StartPlayerGivesFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ SuspendGivesAwayAudioFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, StopGivesAwayAudioFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeGivesBackAudioFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+ SystemResume();
+
+ EXPECT_TRUE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ RemovingLastPlayerDropsAudioFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer.get(), 0);
+ EXPECT_TRUE(HasAudioFocus());
+ RemovePlayer(player_observer.get(), 1);
+ EXPECT_TRUE(HasAudioFocus());
+ RemovePlayer(player_observer.get(), 2);
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ RemovingLastPlayerFromManyObserversDropsAudioFocus) {
+ auto player_observer_1 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ auto player_observer_2 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ auto player_observer_3 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_3.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer_1.get(), 0);
+ EXPECT_TRUE(HasAudioFocus());
+ RemovePlayer(player_observer_2.get(), 0);
+ EXPECT_TRUE(HasAudioFocus());
+ RemovePlayer(player_observer_3.get(), 0);
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ RemovingAllPlayersFromObserversDropsAudioFocus) {
+ auto player_observer_1 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ auto player_observer_2 = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
+
+ RemovePlayers(player_observer_1.get());
+ EXPECT_TRUE(HasAudioFocus());
+ RemovePlayers(player_observer_2.get());
+ EXPECT_FALSE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumePlayGivesAudioFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer.get(), 0);
+ EXPECT_FALSE(HasAudioFocus());
+
+ EXPECT_TRUE(
+ AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
+ EXPECT_TRUE(HasAudioFocus());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ResumeSuspendAreSentOnlyOncePerPlayers) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
+
+ SystemSuspend(true);
+ EXPECT_EQ(3, player_observer->received_suspend_calls());
+
+ SystemResume();
+ EXPECT_EQ(3, player_observer->received_resume_calls());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ResumeSuspendAreSentOnlyOncePerPlayersAddedTwice) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ // Adding the three players above again.
+ EXPECT_TRUE(
+ AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
+ EXPECT_TRUE(
+ AddPlayer(player_observer.get(), 1, media::MediaContentType::Persistent));
+ EXPECT_TRUE(
+ AddPlayer(player_observer.get(), 2, media::MediaContentType::Persistent));
+
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
+
+ SystemSuspend(true);
+ EXPECT_EQ(3, player_observer->received_suspend_calls());
+
+ SystemResume();
+ EXPECT_EQ(3, player_observer->received_resume_calls());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ RemovingTheSamePlayerTwiceIsANoop) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer.get(), 0);
+ RemovePlayer(player_observer.get(), 0);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ // Starting a player with a given type should set the session to that type.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
+ GetSessionAudioFocusType());
+
+ // Adding a player of the same type should have no effect on the type.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::GainTransientMayDuck,
+ GetSessionAudioFocusType());
+
+ // Adding a player of Content type should override the current type.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
+ GetSessionAudioFocusType());
+
+ // Adding a player of the Transient type should have no effect on the type.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
+ GetSessionAudioFocusType());
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(player_observer->IsPlaying(2));
+ EXPECT_TRUE(player_observer->IsPlaying(3));
+
+ SystemSuspend(true);
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+ EXPECT_FALSE(player_observer->IsPlaying(2));
+ EXPECT_FALSE(player_observer->IsPlaying(3));
+
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
+ GetSessionAudioFocusType());
+
+ SystemResume();
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(player_observer->IsPlaying(2));
+ EXPECT_TRUE(player_observer->IsPlaying(3));
+
+ EXPECT_EQ(content::AudioFocusManager::AudioFocusType::Gain,
+ GetSessionAudioFocusType());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsShowForContent) {
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ // Starting a player with a content type should show the media controls.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsNoShowForTransient) {
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, false));
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ // Starting a player with a transient type should not show the media controls.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsHideWhenStopped) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayers(player_observer.get());
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsShownAcceptTransient) {
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ // Transient player join the session without affecting the controls.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsShownAfterContentAdded) {
+ Expectation dontShowControls = EXPECT_CALL(
+ *mock_media_session_observer(), MediaSessionStateChanged(false, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(dontShowControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ // The controls are shown when the content player is added.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsStayIfOnlyOnePlayerHasBeenPaused) {
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ // Removing only content player doesn't hide the controls since the session
+ // is still active.
+ RemovePlayer(player_observer.get(), 0);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsHideWhenTheLastPlayerIsRemoved) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer.get(), 0);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+
+ RemovePlayer(player_observer.get(), 1);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsHideWhenAllThePlayersAreRemoved) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayers(player_observer.get());
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsNotHideWhenTheLastPlayerIsPaused) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ OnPlayerPaused(player_observer.get(), 0);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+
+ OnPlayerPaused(player_observer.get(), 1);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ SuspendTemporaryUpdatesControls) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsUpdatedWhenResumed) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(true);
+ SystemResume();
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsHideWhenSessionSuspendedPermanently) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(false);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ConstrolsHideWhenSessionStops) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsHideWhenSessionChangesFromContentToTransient) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, false))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(true);
+
+ // This should reset the session and change it to a transient, so
+ // hide the controls.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsUpdatedWhenNewPlayerResetsSession) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(true);
+
+ // This should reset the session and update the controls.
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsResumedWhenPlayerIsResumed) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(true);
+
+ // This should resume the session and update the controls.
+ AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsUpdatedDueToResumeSessionAction) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ UISuspend();
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsUpdatedDueToSuspendSessionAction) {
+ Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false));
+ Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, true))
+ .After(showControls);
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(pauseControls);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ UISuspend();
+ UIResume();
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsDontShowWhenOneShotIsPresent) {
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, false));
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsHiddenAfterRemoveOneShotWithoutOtherPlayers) {
+ Expectation expect_1 = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, false));
+ Expectation expect_2 = EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(false, true))
+ .After(expect_1);
+ EXPECT_CALL(*mock_media_session_observer(), MediaSessionStateChanged(true, _))
+ .Times(0)
+ .After(expect_2);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ RemovePlayer(player_observer.get(), 0);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ ControlsShowAfterRemoveOneShotWithPersistentPresent) {
+ Expectation uncontrollable = EXPECT_CALL(
+ *mock_media_session_observer(), MediaSessionStateChanged(false, false));
+
+ EXPECT_CALL(*mock_media_session_observer(),
+ MediaSessionStateChanged(true, false))
+ .After(uncontrollable);
+
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ RemovePlayer(player_observer.get(), 0);
+
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ DontSuspendWhenOneShotIsPresent) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(false);
+
+ EXPECT_FALSE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ DontResumeBySystemUISuspendedSessions) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ UISuspend();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+
+ SystemResume();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ AllowUIResumeForSystemSuspend) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+
+ UIResume();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeSuspendFromUI) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ UISuspend();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+
+ UIResume();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeSuspendFromSystem) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ SystemSuspend(true);
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsSuspended());
+
+ SystemResume();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_FALSE(IsSuspended());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, OneShotTakesGainFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ EXPECT_CALL(
+ *mock_audio_focus_delegate(),
+ RequestAudioFocus(content::AudioFocusManager::AudioFocusType::Gain))
+ .Times(1);
+ EXPECT_CALL(*mock_audio_focus_delegate(),
+ RequestAudioFocus(::testing::Ne(
+ content::AudioFocusManager::AudioFocusType::Gain)))
+ .Times(0);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, RemovingOneShotDropsFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ EXPECT_CALL(*mock_audio_focus_delegate(), AbandonAudioFocus());
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ RemovePlayer(player_observer.get(), 0);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ RemovingOneShotWhileStillHavingOtherPlayersKeepsFocus) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ EXPECT_CALL(*mock_audio_focus_delegate(), AbandonAudioFocus())
+ .Times(1); // Called in TearDown
+ StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ RemovePlayer(player_observer.get(), 0);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_Suspended_SystemTransient) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(true);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(0, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_Suspended_SystemPermantent) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ SystemSuspend(false);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(0, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(1, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(0, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_UI) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ UISuspend();
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(0, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(1, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Multiple) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ UISuspend();
+ UIResume();
+
+ SystemSuspend(true);
+ SystemResume();
+
+ UISuspend();
+ UIResume();
+
+ SystemSuspend(false);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(4, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(1, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(2, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Crossing) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ UISuspend();
+ SystemSuspend(true);
+ SystemSuspend(false);
+ UIResume();
+
+ SystemSuspend(true);
+ SystemSuspend(true);
+ SystemSuspend(false);
+ SystemResume();
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(2, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(1, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Stop) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(0, samples->GetCount(0)); // System Transient
+ EXPECT_EQ(0, samples->GetCount(1)); // System Permanent
+ EXPECT_EQ(1, samples->GetCount(2)); // UI
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_NoActivation) {
+ base::HistogramTester tester;
+
+ std::unique_ptr<MediaSessionImpl> media_session = CreateDummyMediaSession();
+ media_session.reset();
+
+ // A MediaSession that wasn't active doesn't register an active time.
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(0, samples->TotalCount());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_SimpleActivation) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(1000));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_ActivationWithUISuspension) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ UISuspend();
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(2000));
+ UIResume();
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(2000));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_ActivationWithSystemSuspension) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ SystemSuspend(true);
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(2000));
+ SystemResume();
+
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(1, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(2000));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_ActivateSuspendedButNotStopped) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ clock->Advance(base::TimeDelta::FromMilliseconds(500));
+ SystemSuspend(true);
+
+ {
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(0, samples->TotalCount());
+ }
+
+ SystemResume();
+ clock->Advance(base::TimeDelta::FromMilliseconds(5000));
+ UISuspend();
+
+ {
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(0, samples->TotalCount());
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_ActivateSuspendStopTwice) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ clock->Advance(base::TimeDelta::FromMilliseconds(500));
+ SystemSuspend(true);
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ clock->Advance(base::TimeDelta::FromMilliseconds(5000));
+ SystemResume();
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(2, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(500));
+ EXPECT_EQ(1, samples->GetCount(5000));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ UMA_ActiveTime_MultipleActivations) {
+ auto player_observer = base::MakeUnique<MockMediaSessionPlayerObserver>();
+ base::HistogramTester tester;
+
+ MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
+ base::SimpleTestTickClock* clock = new base::SimpleTestTickClock();
+ clock->SetNowTicks(base::TimeTicks::Now());
+ media_session_uma_helper->SetClockForTest(
+ std::unique_ptr<base::SimpleTestTickClock>(clock));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ clock->Advance(base::TimeDelta::FromMilliseconds(10000));
+ RemovePlayer(player_observer.get(), 0);
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ clock->Advance(base::TimeDelta::FromMilliseconds(1000));
+ media_session_->Stop(MediaSession::SuspendType::UI);
+
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
+ EXPECT_EQ(2, samples->TotalCount());
+ EXPECT_EQ(1, samples->GetCount(1000));
+ EXPECT_EQ(1, samples->GetCount(10000));
+}
diff --git a/chromium/content/browser/media/session/media_session_visibility_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index 01e42325551..a6840e57edf 100644
--- a/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -8,8 +8,9 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -54,39 +55,37 @@ struct VisibilityTestData {
SessionState session_state_before_hide;
SessionState session_state_after_hide;
};
-
}
-
// Base class of MediaSession visibility tests. The class is intended
// to be used to run tests under different configurations. Tests
// should inheret from this class, set up their own command line per
// their configuration, and use macro INCLUDE_TEST_FROM_BASE_CLASS to
// include required tests. See
// media_session_visibility_browsertest_instances.cc for examples.
-class MediaSessionVisibilityBrowserTest
+class MediaSessionImplVisibilityBrowserTest
: public ContentBrowserTest,
public ::testing::WithParamInterface<
std::tr1::tuple<VisibilityTestData, Pipeline>> {
public:
- MediaSessionVisibilityBrowserTest() = default;
- ~MediaSessionVisibilityBrowserTest() override = default;
+ MediaSessionImplVisibilityBrowserTest() = default;
+ ~MediaSessionImplVisibilityBrowserTest() override = default;
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
web_contents_ = shell()->web_contents();
- media_session_ = MediaSession::Get(web_contents_);
+ media_session_ = MediaSessionImpl::Get(web_contents_);
- media_session_state_loop_runners_[MediaSession::State::ACTIVE] =
+ media_session_state_loop_runners_[MediaSessionImpl::State::ACTIVE] =
new MessageLoopRunner();
- media_session_state_loop_runners_[MediaSession::State::SUSPENDED] =
+ media_session_state_loop_runners_[MediaSessionImpl::State::SUSPENDED] =
new MessageLoopRunner();
- media_session_state_loop_runners_[MediaSession::State::INACTIVE] =
+ media_session_state_loop_runners_[MediaSessionImpl::State::INACTIVE] =
new MessageLoopRunner();
media_session_state_callback_subscription_ =
media_session_->RegisterMediaSessionStateChangedCallbackForTest(
- base::Bind(&MediaSessionVisibilityBrowserTest::
- OnMediaSessionStateChanged,
+ base::Bind(&MediaSessionImplVisibilityBrowserTest::
+ OnMediaSessionStateChanged,
base::Unretained(this)));
}
@@ -97,26 +96,17 @@ class MediaSessionVisibilityBrowserTest
}
void EnableDisableResumingBackgroundVideos(bool enable) {
- std::string enabled_features;
- std::string disabled_features;
if (enable)
- enabled_features = media::kResumeBackgroundVideo.name;
+ scoped_feature_list_.InitAndEnableFeature(media::kResumeBackgroundVideo);
else
- disabled_features = media::kResumeBackgroundVideo.name;
-
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- enabled_features, disabled_features);
- base::FeatureList::ClearInstanceForTesting();
- base::FeatureList::SetInstance(std::move(feature_list));
+ scoped_feature_list_.InitAndDisableFeature(media::kResumeBackgroundVideo);
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(
switches::kDisableGestureRequirementForMediaPlayback);
#if !defined(OS_ANDROID)
- command_line->AppendSwitch(
- switches::kEnableDefaultMediaSession);
+ command_line->AppendSwitch(switches::kEnableDefaultMediaSession);
#endif // !defined(OS_ANDROID)
VisibilityTestData params = GetVisibilityTestData();
@@ -152,23 +142,23 @@ class MediaSessionVisibilityBrowserTest
ClearMediaSessionStateLoopRunners();
RunScript(kStartPlayerScript);
LOG(INFO) << "Waiting for session to be active";
- WaitForMediaSessionState(MediaSession::State::ACTIVE);
+ WaitForMediaSessionState(MediaSessionImpl::State::ACTIVE);
}
// Maybe pause the player depending on whether the session state before hide
// is SUSPENDED.
void MaybePausePlayer() {
- ASSERT_TRUE(GetVisibilityTestData().session_state_before_hide
- != SessionState::INACTIVE);
- if (GetVisibilityTestData().session_state_before_hide
- == SessionState::ACTIVE)
+ ASSERT_TRUE(GetVisibilityTestData().session_state_before_hide !=
+ SessionState::INACTIVE);
+ if (GetVisibilityTestData().session_state_before_hide ==
+ SessionState::ACTIVE)
return;
LOG(INFO) << "Pausing player";
ClearMediaSessionStateLoopRunners();
RunScript(kPausePlayerScript);
LOG(INFO) << "Waiting for session to be suspended";
- WaitForMediaSessionState(MediaSession::State::SUSPENDED);
+ WaitForMediaSessionState(MediaSessionImpl::State::SUSPENDED);
}
void HideTab() {
@@ -178,9 +168,9 @@ class MediaSessionVisibilityBrowserTest
}
void CheckSessionStateAfterHide() {
- MediaSession::State state_before_hide =
+ MediaSessionImpl::State state_before_hide =
ToMediaSessionState(GetVisibilityTestData().session_state_before_hide);
- MediaSession::State state_after_hide =
+ MediaSessionImpl::State state_after_hide =
ToMediaSessionState(GetVisibilityTestData().session_state_after_hide);
if (state_before_hide == state_after_hide) {
@@ -211,7 +201,7 @@ class MediaSessionVisibilityBrowserTest
state_loop_runner.second = new MessageLoopRunner();
}
- void OnMediaSessionStateChanged(MediaSession::State state) {
+ void OnMediaSessionStateChanged(MediaSessionImpl::State state) {
ASSERT_TRUE(media_session_state_loop_runners_.count(state));
media_session_state_loop_runners_[state]->Quit();
}
@@ -225,85 +215,86 @@ class MediaSessionVisibilityBrowserTest
run_loop.Run();
}
- void WaitForMediaSessionState(MediaSession::State state) {
+ void WaitForMediaSessionState(MediaSessionImpl::State state) {
ASSERT_TRUE(media_session_state_loop_runners_.count(state));
media_session_state_loop_runners_[state]->Run();
}
- MediaSession::State ToMediaSessionState(SessionState state) {
+ MediaSessionImpl::State ToMediaSessionState(SessionState state) {
switch (state) {
case SessionState::ACTIVE:
- return MediaSession::State::ACTIVE;
+ return MediaSessionImpl::State::ACTIVE;
break;
case SessionState::SUSPENDED:
- return MediaSession::State::SUSPENDED;
+ return MediaSessionImpl::State::SUSPENDED;
break;
case SessionState::INACTIVE:
- return MediaSession::State::INACTIVE;
+ return MediaSessionImpl::State::INACTIVE;
break;
default:
ADD_FAILURE() << "invalid SessionState to convert";
- return MediaSession::State::INACTIVE;
+ return MediaSessionImpl::State::INACTIVE;
}
}
WebContents* web_contents_;
- MediaSession* media_session_;
+ MediaSessionImpl* media_session_;
// MessageLoopRunners for waiting MediaSession state to change. Note that the
// MessageLoopRunners can accept Quit() before calling Run(), thus the state
// change can still be captured before waiting. For example, the MediaSession
// might go active immediately after calling HTMLMediaElement.play(). A test
// can listen to the state change before calling play(), and then wait for the
// state change after play().
- std::map<MediaSession::State, scoped_refptr<MessageLoopRunner> >
- media_session_state_loop_runners_;
- std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
+ std::map<MediaSessionImpl::State, scoped_refptr<MessageLoopRunner>>
+ media_session_state_loop_runners_;
+ std::unique_ptr<
+ base::CallbackList<void(MediaSessionImpl::State)>::Subscription>
media_session_state_callback_subscription_;
+ base::test::ScopedFeatureList scoped_feature_list_;
- DISALLOW_COPY_AND_ASSIGN(MediaSessionVisibilityBrowserTest);
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionImplVisibilityBrowserTest);
};
namespace {
VisibilityTestData kTestParams[] = {
- { MediaSuspend::ENABLED, BackgroundResuming::DISABLED,
- SessionState::SUSPENDED, SessionState::INACTIVE },
- { MediaSuspend::ENABLED, BackgroundResuming::DISABLED,
- SessionState::ACTIVE, SessionState::INACTIVE },
- { MediaSuspend::ENABLED, BackgroundResuming::ENABLED,
- SessionState::ACTIVE, SessionState::SUSPENDED },
- { MediaSuspend::ENABLED, BackgroundResuming::ENABLED,
- SessionState::SUSPENDED, SessionState::SUSPENDED },
- { MediaSuspend::DISABLED, BackgroundResuming::DISABLED,
- SessionState::SUSPENDED, SessionState::SUSPENDED },
- { MediaSuspend::DISABLED, BackgroundResuming::DISABLED,
- SessionState::ACTIVE, SessionState::ACTIVE },
- { MediaSuspend::DISABLED, BackgroundResuming::ENABLED,
- SessionState::ACTIVE, SessionState::ACTIVE },
- { MediaSuspend::DISABLED, BackgroundResuming::ENABLED,
- SessionState::SUSPENDED, SessionState::SUSPENDED },
+ {MediaSuspend::ENABLED, BackgroundResuming::DISABLED,
+ SessionState::SUSPENDED, SessionState::INACTIVE},
+ {MediaSuspend::ENABLED, BackgroundResuming::DISABLED, SessionState::ACTIVE,
+ SessionState::INACTIVE},
+ {MediaSuspend::ENABLED, BackgroundResuming::ENABLED, SessionState::ACTIVE,
+ SessionState::SUSPENDED},
+ {MediaSuspend::ENABLED, BackgroundResuming::ENABLED,
+ SessionState::SUSPENDED, SessionState::SUSPENDED},
+ {MediaSuspend::DISABLED, BackgroundResuming::DISABLED,
+ SessionState::SUSPENDED, SessionState::SUSPENDED},
+ {MediaSuspend::DISABLED, BackgroundResuming::DISABLED, SessionState::ACTIVE,
+ SessionState::ACTIVE},
+ {MediaSuspend::DISABLED, BackgroundResuming::ENABLED, SessionState::ACTIVE,
+ SessionState::ACTIVE},
+ {MediaSuspend::DISABLED, BackgroundResuming::ENABLED,
+ SessionState::SUSPENDED, SessionState::SUSPENDED},
};
Pipeline kPipelines[] = {
Pipeline::WMPI,
#if defined(OS_ANDROID)
- // Disabling WMPA tests because of https://crbug.com/646312
- // Pipeline::WMPA,
+// Disabling WMPA tests because of https://crbug.com/646312
+// Pipeline::WMPA,
#endif // defined(OS_ANDROID)
};
} // anonymous namespace
-IN_PROC_BROWSER_TEST_P(MediaSessionVisibilityBrowserTest,
- TestEntryPoint) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplVisibilityBrowserTest, TestEntryPoint) {
StartPlayer();
MaybePausePlayer();
HideTab();
CheckSessionStateAfterHide();
}
-INSTANTIATE_TEST_CASE_P(MediaSessionVisibilityBrowserTestInstances,
- MediaSessionVisibilityBrowserTest,
+INSTANTIATE_TEST_CASE_P(MediaSessionImplVisibilityBrowserTestInstances,
+ MediaSessionImplVisibilityBrowserTest,
::testing::Combine(::testing::ValuesIn(kTestParams),
::testing::ValuesIn(kPipelines)));
diff --git a/chromium/content/browser/media/session/media_session_observer.h b/chromium/content/browser/media/session/media_session_player_observer.h
index 4d9f4d498c2..95ba2613b53 100644
--- a/chromium/content/browser/media/session/media_session_observer.h
+++ b/chromium/content/browser/media/session/media_session_player_observer.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
-#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_PLAYER_OBSERVER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_PLAYER_OBSERVER_H_
namespace content {
-class MediaSessionObserver {
+class MediaSessionPlayerObserver {
public:
- MediaSessionObserver() = default;
- virtual ~MediaSessionObserver() = default;
+ MediaSessionPlayerObserver() = default;
+ virtual ~MediaSessionPlayerObserver() = default;
// The given |player_id| has been suspended by the MediaSession.
virtual void OnSuspend(int player_id) = 0;
@@ -26,4 +26,4 @@ class MediaSessionObserver {
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_PLAYER_OBSERVER_H_
diff --git a/chromium/content/browser/media/session/media_session_service_impl.cc b/chromium/content/browser/media/session/media_session_service_impl.cc
new file mode 100644
index 00000000000..589823fab2b
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_service_impl.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_service_impl.h"
+
+#include "content/browser/media/session/media_metadata_sanitizer.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+MediaSessionServiceImpl::MediaSessionServiceImpl(
+ RenderFrameHost* render_frame_host)
+ : render_frame_host_(render_frame_host) {
+ MediaSessionImpl* session = GetMediaSession();
+ if (session)
+ session->SetMediaSessionService(this);
+}
+
+MediaSessionServiceImpl::~MediaSessionServiceImpl() {
+ MediaSessionImpl* session = GetMediaSession();
+ if (session && session->GetMediaSessionService() == this)
+ session->SetMediaSessionService(nullptr);
+}
+
+// static
+void MediaSessionServiceImpl::Create(
+ RenderFrameHost* render_frame_host,
+ blink::mojom::MediaSessionServiceRequest request) {
+ MediaSessionServiceImpl* impl =
+ new MediaSessionServiceImpl(render_frame_host);
+ impl->Bind(std::move(request));
+}
+
+void MediaSessionServiceImpl::SetClient(
+ blink::mojom::MediaSessionClientPtr client) {
+ client_ = std::move(client);
+}
+
+void MediaSessionServiceImpl::SetMetadata(
+ const base::Optional<content::MediaMetadata>& metadata) {
+ // When receiving a MediaMetadata, the browser process can't trust that it is
+ // coming from a known and secure source. It must be processed accordingly.
+ if (metadata.has_value() &&
+ !MediaMetadataSanitizer::CheckSanity(metadata.value())) {
+ render_frame_host_->GetProcess()->ShutdownForBadMessage(
+ RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
+ return;
+ }
+
+ MediaSessionImpl* session = GetMediaSession();
+ if (session)
+ session->SetMetadata(metadata);
+}
+
+void MediaSessionServiceImpl::EnableAction(
+ blink::mojom::MediaSessionAction action) {
+ MediaSessionImpl* session = GetMediaSession();
+ if (session)
+ session->OnMediaSessionEnabledAction(action);
+}
+
+void MediaSessionServiceImpl::DisableAction(
+ blink::mojom::MediaSessionAction action) {
+ MediaSessionImpl* session = GetMediaSession();
+ if (session)
+ session->OnMediaSessionDisabledAction(action);
+}
+
+MediaSessionImpl* MediaSessionServiceImpl::GetMediaSession() {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ WebContentsImpl::FromRenderFrameHost(render_frame_host_));
+ if (!contents)
+ return nullptr;
+ if (render_frame_host_ != contents->GetMainFrame())
+ return nullptr;
+ return MediaSessionImpl::Get(contents);
+}
+
+void MediaSessionServiceImpl::Bind(
+ blink::mojom::MediaSessionServiceRequest request) {
+ binding_.reset(new mojo::Binding<blink::mojom::MediaSessionService>(
+ this, std::move(request)));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/media_session_service_impl.h b/chromium/content/browser/media/session/media_session_service_impl.h
index dcd1b35f177..37629c37f38 100644
--- a/chromium/content/browser/media/android/media_session_service_impl.h
+++ b/chromium/content/browser/media/session/media_session_service_impl.h
@@ -2,40 +2,56 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_SERVICE_IMPL_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_SERVICE_IMPL_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_
+#include "base/optional.h"
+#include "content/public/common/media_metadata.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h"
namespace content {
+class MediaSessionImpl;
class RenderFrameHost;
+// There is one MediaSessionService per frame.
class MediaSessionServiceImpl : public blink::mojom::MediaSessionService {
public:
~MediaSessionServiceImpl() override;
static void Create(RenderFrameHost* render_frame_host,
blink::mojom::MediaSessionServiceRequest request);
+ const blink::mojom::MediaSessionClientPtr& GetClient() { return client_; }
private:
explicit MediaSessionServiceImpl(RenderFrameHost* render_frame_host);
+ // blink::mojom::MediaSessionService implementation.
+ void SetClient(blink::mojom::MediaSessionClientPtr client) override;
+
void SetMetadata(
const base::Optional<content::MediaMetadata>& metadata) override;
+ void EnableAction(blink::mojom::MediaSessionAction action) override;
+ void DisableAction(blink::mojom::MediaSessionAction action) override;
+
+ // Returns the content::MediaSession this service is associated with. Only
+ // returns non-null when this service is in the top-level frame.
+ MediaSessionImpl* GetMediaSession();
+
void Bind(blink::mojom::MediaSessionServiceRequest request);
RenderFrameHost* render_frame_host_;
- // RAII binding of |this| to an MediaSession interface request.
+ // RAII binding of |this| to an MediaSessionService interface request.
// The binding is removed when binding_ is cleared or goes out of scope.
std::unique_ptr<mojo::Binding<blink::mojom::MediaSessionService>> binding_;
+ blink::mojom::MediaSessionClientPtr client_;
DISALLOW_COPY_AND_ASSIGN(MediaSessionServiceImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_SERVICE_IMPL_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/media/session/mock_media_session_observer.cc b/chromium/content/browser/media/session/mock_media_session_player_observer.cc
index edc213a1090..b26bc40010d 100644
--- a/chromium/content/browser/media/session/mock_media_session_observer.cc
+++ b/chromium/content/browser/media/session/mock_media_session_player_observer.cc
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/session/mock_media_session_observer.h"
+#include "content/browser/media/session/mock_media_session_player_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-MockMediaSessionObserver::MockMediaSessionObserver() = default;
+MockMediaSessionPlayerObserver::MockMediaSessionPlayerObserver() = default;
-MockMediaSessionObserver::~MockMediaSessionObserver() = default;
+MockMediaSessionPlayerObserver::~MockMediaSessionPlayerObserver() = default;
-void MockMediaSessionObserver::OnSuspend(int player_id) {
+void MockMediaSessionPlayerObserver::OnSuspend(int player_id) {
EXPECT_GE(player_id, 0);
EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
@@ -20,7 +20,7 @@ void MockMediaSessionObserver::OnSuspend(int player_id) {
players_[player_id].is_playing_ = false;
}
-void MockMediaSessionObserver::OnResume(int player_id) {
+void MockMediaSessionPlayerObserver::OnResume(int player_id) {
EXPECT_GE(player_id, 0);
EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
@@ -28,8 +28,9 @@ void MockMediaSessionObserver::OnResume(int player_id) {
players_[player_id].is_playing_ = true;
}
-void MockMediaSessionObserver::OnSetVolumeMultiplier(
- int player_id, double volume_multiplier) {
+void MockMediaSessionPlayerObserver::OnSetVolumeMultiplier(
+ int player_id,
+ double volume_multiplier) {
EXPECT_GE(player_id, 0);
EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
@@ -39,31 +40,32 @@ void MockMediaSessionObserver::OnSetVolumeMultiplier(
players_[player_id].volume_multiplier_ = volume_multiplier;
}
-int MockMediaSessionObserver::StartNewPlayer() {
+int MockMediaSessionPlayerObserver::StartNewPlayer() {
players_.push_back(MockPlayer(true, 1.0f));
return players_.size() - 1;
}
-bool MockMediaSessionObserver::IsPlaying(size_t player_id) {
+bool MockMediaSessionPlayerObserver::IsPlaying(size_t player_id) {
EXPECT_GT(players_.size(), player_id);
return players_[player_id].is_playing_;
}
-double MockMediaSessionObserver::GetVolumeMultiplier(size_t player_id) {
+double MockMediaSessionPlayerObserver::GetVolumeMultiplier(size_t player_id) {
EXPECT_GT(players_.size(), player_id);
return players_[player_id].volume_multiplier_;
}
-void MockMediaSessionObserver::SetPlaying(size_t player_id, bool playing) {
+void MockMediaSessionPlayerObserver::SetPlaying(size_t player_id,
+ bool playing) {
EXPECT_GT(players_.size(), player_id);
players_[player_id].is_playing_ = playing;
}
-int MockMediaSessionObserver::received_suspend_calls() const {
+int MockMediaSessionPlayerObserver::received_suspend_calls() const {
return received_suspend_calls_;
}
-int MockMediaSessionObserver::received_resume_calls() const {
+int MockMediaSessionPlayerObserver::received_resume_calls() const {
return received_resume_calls_;
}
diff --git a/chromium/content/browser/media/session/mock_media_session_observer.h b/chromium/content/browser/media/session/mock_media_session_player_observer.h
index 03913bced06..824db68a9c6 100644
--- a/chromium/content/browser/media/session/mock_media_session_observer.h
+++ b/chromium/content/browser/media/session/mock_media_session_player_observer.h
@@ -5,18 +5,18 @@
#include <stddef.h>
#include <vector>
-#include "content/browser/media/session/media_session_observer.h"
+#include "content/browser/media/session/media_session_player_observer.h"
namespace content {
-// MockMediaSessionObserver is a mock implementation of MediaSessionObserver to
-// be used in tests.
-class MockMediaSessionObserver : public MediaSessionObserver {
+// MockMediaSessionPlayerObserver is a mock implementation of
+// MediaSessionPlayerObserver to be used in tests.
+class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
public:
- MockMediaSessionObserver();
- ~MockMediaSessionObserver() override;
+ MockMediaSessionPlayerObserver();
+ ~MockMediaSessionPlayerObserver() override;
- // Implements MediaSessionObserver.
+ // Implements MediaSessionPlayerObserver.
void OnSuspend(int player_id) override;
void OnResume(int player_id) override;
void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
@@ -42,8 +42,7 @@ class MockMediaSessionObserver : public MediaSessionObserver {
struct MockPlayer {
public:
MockPlayer(bool is_playing = true, double volume_multiplier = 1.0f)
- : is_playing_(is_playing),
- volume_multiplier_(volume_multiplier) {}
+ : is_playing_(is_playing), volume_multiplier_(volume_multiplier) {}
bool is_playing_;
double volume_multiplier_;
};
diff --git a/chromium/content/browser/media/session/pepper_playback_observer.cc b/chromium/content/browser/media/session/pepper_playback_observer.cc
index 8132f3ea380..593d3d72778 100644
--- a/chromium/content/browser/media/session/pepper_playback_observer.cc
+++ b/chromium/content/browser/media/session/pepper_playback_observer.cc
@@ -6,7 +6,7 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/media/session/pepper_player_delegate.h"
#include "content/common/frame_messages.h"
#include "ipc/ipc_message_macros.h"
@@ -15,6 +15,16 @@
namespace content {
+namespace {
+
+bool ShouldDuckFlash() {
+ return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kEnableDefaultMediaSession) ==
+ switches::kEnableDefaultMediaSessionDuckFlash;
+}
+
+} // anonymous namespace
+
PepperPlaybackObserver::PepperPlaybackObserver(WebContentsImpl *contents)
: contents_(contents) {}
@@ -25,7 +35,7 @@ PepperPlaybackObserver::~PepperPlaybackObserver() {
// RenderViewHost has been destroyed.
for (PlayersMap::iterator iter = players_map_.begin();
iter != players_map_.end();) {
- MediaSession::Get(contents_)->RemovePlayer(
+ MediaSessionImpl::Get(contents_)->RemovePlayer(
iter->second.get(), PepperPlayerDelegate::kPlayerId);
iter = players_map_.erase(iter);
}
@@ -46,25 +56,23 @@ void PepperPlaybackObserver::PepperInstanceDeleted(int32_t pp_instance) {
void PepperPlaybackObserver::PepperStartsPlayback(int32_t pp_instance) {
players_played_sound_map_[pp_instance] = true;
- if (!base::FeatureList::IsEnabled(media::kFlashJoinsMediaSession))
- return;
-
if (players_map_.count(pp_instance))
return;
players_map_[pp_instance].reset(new PepperPlayerDelegate(
contents_, pp_instance));
- MediaSession::Get(contents_)->AddPlayer(
- players_map_[pp_instance].get(),
- PepperPlayerDelegate::kPlayerId,
- media::MediaContentType::Pepper);
+
+ MediaSessionImpl::Get(contents_)->AddPlayer(
+ players_map_[pp_instance].get(), PepperPlayerDelegate::kPlayerId,
+ ShouldDuckFlash() ? media::MediaContentType::Pepper
+ : media::MediaContentType::OneShot);
}
void PepperPlaybackObserver::PepperStopsPlayback(int32_t pp_instance) {
if (!players_map_.count(pp_instance))
return;
- MediaSession::Get(contents_)->RemovePlayer(
+ MediaSessionImpl::Get(contents_)->RemovePlayer(
players_map_[pp_instance].get(), PepperPlayerDelegate::kPlayerId);
players_map_.erase(pp_instance);
diff --git a/chromium/content/browser/media/session/pepper_playback_observer.h b/chromium/content/browser/media/session/pepper_playback_observer.h
index 3b43e197261..9aacf007dbf 100644
--- a/chromium/content/browser/media/session/pepper_playback_observer.h
+++ b/chromium/content/browser/media/session/pepper_playback_observer.h
@@ -26,7 +26,9 @@ class PepperPlaybackObserver {
void PepperInstanceCreated(int32_t pp_instance);
void PepperInstanceDeleted(int32_t pp_instance);
+ // This method is called when a Pepper instance starts making sound.
void PepperStartsPlayback(int32_t pp_instance);
+ // This method is called when a Pepper instance stops making sound.
void PepperStopsPlayback(int32_t pp_instance);
private:
diff --git a/chromium/content/browser/media/session/pepper_player_delegate.cc b/chromium/content/browser/media/session/pepper_player_delegate.cc
index 8c38b2a57e5..7b95734faa6 100644
--- a/chromium/content/browser/media/session/pepper_player_delegate.cc
+++ b/chromium/content/browser/media/session/pepper_player_delegate.cc
@@ -8,6 +8,7 @@
#include "content/browser/media/session/pepper_playback_observer.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
+#include "media/base/media_switches.h"
namespace content {
@@ -15,6 +16,12 @@ namespace {
const double kDuckVolume = 0.2f;
+bool ShouldDuckFlash() {
+ return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kEnableDefaultMediaSession) ==
+ switches::kEnableDefaultMediaSessionDuckFlash;
+}
+
} // anonymous namespace
const int PepperPlayerDelegate::kPlayerId = 0;
@@ -27,18 +34,27 @@ PepperPlayerDelegate::PepperPlayerDelegate(
PepperPlayerDelegate::~PepperPlayerDelegate() = default;
void PepperPlayerDelegate::OnSuspend(int player_id) {
+ if (!ShouldDuckFlash())
+ return;
+
// Pepper player cannot be really suspended. Duck the volume instead.
DCHECK_EQ(player_id, kPlayerId);
SetVolume(player_id, kDuckVolume);
}
void PepperPlayerDelegate::OnResume(int player_id) {
+ if (!ShouldDuckFlash())
+ return;
+
DCHECK_EQ(player_id, kPlayerId);
SetVolume(player_id, 1.0f);
}
void PepperPlayerDelegate::OnSetVolumeMultiplier(int player_id,
double volume_multiplier) {
+ if (!ShouldDuckFlash())
+ return;
+
DCHECK_EQ(player_id, kPlayerId);
SetVolume(player_id, volume_multiplier);
}
diff --git a/chromium/content/browser/media/session/pepper_player_delegate.h b/chromium/content/browser/media/session/pepper_player_delegate.h
index bf3a39bd83d..f2faa8d8bc1 100644
--- a/chromium/content/browser/media/session/pepper_player_delegate.h
+++ b/chromium/content/browser/media/session/pepper_player_delegate.h
@@ -6,14 +6,12 @@
#define CONTENT_BROWSER_MEDIA_SESSION_PEPPER_PLAYER_DELEGATE_H_
#include "base/macros.h"
-#include "content/browser/media/session/media_session_observer.h"
+#include "content/browser/media/session/media_session_player_observer.h"
#include "content/browser/web_contents/web_contents_impl.h"
namespace content {
-class PepperWebContentsObserver;
-
-class PepperPlayerDelegate : public MediaSessionObserver {
+class PepperPlayerDelegate : public MediaSessionPlayerObserver {
public:
// The Id can only be 0 for PepperPlayerDelegate. Declare the constant here so
// it can be used elsewhere.
@@ -23,7 +21,7 @@ class PepperPlayerDelegate : public MediaSessionObserver {
WebContentsImpl* contents, int32_t pp_instance);
~PepperPlayerDelegate() override;
- // MediaSessionObserver implementation.
+ // MediaSessionPlayerObserver implementation.
void OnSuspend(int player_id) override;
void OnResume(int player_id) override;
void OnSetVolumeMultiplier(int player_id,
diff --git a/chromium/content/browser/media/android/url_provision_fetcher.cc b/chromium/content/browser/media/url_provision_fetcher.cc
index 446d1a76051..0d08d74a5ff 100644
--- a/chromium/content/browser/media/android/url_provision_fetcher.cc
+++ b/chromium/content/browser/media/url_provision_fetcher.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/android/url_provision_fetcher.h"
+#include "content/browser/media/url_provision_fetcher.h"
#include "base/memory/ptr_util.h"
-#include "content/public/browser/android/provision_fetcher_factory.h"
+#include "content/public/browser/provision_fetcher_factory.h"
#include "media/base/bind_to_current_loop.h"
#include "net/url_request/url_fetcher.h"
@@ -61,7 +61,6 @@ void URLProvisionFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
}
request_.reset();
-
// URLFetcher implementation calls OnURLFetchComplete() on the same thread
// that called Start() and it does this asynchronously.
response_cb_.Run(success, response);
diff --git a/chromium/content/browser/media/android/url_provision_fetcher.h b/chromium/content/browser/media/url_provision_fetcher.h
index b551c3b0345..02a594b7347 100644
--- a/chromium/content/browser/media/android/url_provision_fetcher.h
+++ b/chromium/content/browser/media/url_provision_fetcher.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_URL_PROVISION_FETCHER_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_URL_PROVISION_FETCHER_H_
+#ifndef CONTENT_BROWSER_MEDIA_URL_PROVISION_FETCHER_H_
+#define CONTENT_BROWSER_MEDIA_URL_PROVISION_FETCHER_H_
#include "base/macros.h"
-#include "media/base/android/provision_fetcher.h"
+#include "media/base/provision_fetcher.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
@@ -38,4 +38,4 @@ class URLProvisionFetcher : public media::ProvisionFetcher,
} // namespace content
-#endif // CHROME_BROWSER_MEDIA_ANDROID_URL_PROVISION_FETCHER_H_
+#endif // CONTENT_BROWSER_MEDIA_URL_PROVISION_FETCHER_H_
diff --git a/chromium/content/browser/memory/memory_coordinator.cc b/chromium/content/browser/memory/memory_coordinator.cc
index 52ee2ece71f..4600029befd 100644
--- a/chromium/content/browser/memory/memory_coordinator.cc
+++ b/chromium/content/browser/memory/memory_coordinator.cc
@@ -5,7 +5,10 @@
#include "content/browser/memory/memory_coordinator.h"
#include "base/memory/memory_coordinator_client_registry.h"
-#include "content/public/common/content_features.h"
+#include "base/metrics/histogram_macros.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_client.h"
namespace content {
@@ -13,35 +16,48 @@ namespace content {
// for the role of this class.
class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle {
public:
- MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request)
- : binding_(this, std::move(request)) {
- }
+ MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request,
+ MemoryCoordinator* coordinator,
+ int render_process_id);
+ ~MemoryCoordinatorHandleImpl() override;
// mojom::MemoryCoordinatorHandle:
- void AddChild(mojom::ChildMemoryCoordinatorPtr child) override {
- DCHECK(!child_.is_bound());
- child_ = std::move(child);
- }
+ void AddChild(mojom::ChildMemoryCoordinatorPtr child) override;
mojom::ChildMemoryCoordinatorPtr& child() { return child_; }
mojo::Binding<mojom::MemoryCoordinatorHandle>& binding() { return binding_; }
private:
+ MemoryCoordinator* coordinator_;
+ int render_process_id_;
mojom::ChildMemoryCoordinatorPtr child_;
mojo::Binding<mojom::MemoryCoordinatorHandle> binding_;
DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorHandleImpl);
};
-// static
-MemoryCoordinator* MemoryCoordinator::GetInstance() {
- if (!base::FeatureList::IsEnabled(features::kMemoryCoordinator))
- return nullptr;
- return base::Singleton<MemoryCoordinator,
- base::LeakySingletonTraits<MemoryCoordinator>>::get();
+MemoryCoordinatorHandleImpl::MemoryCoordinatorHandleImpl(
+ mojom::MemoryCoordinatorHandleRequest request,
+ MemoryCoordinator* coordinator,
+ int render_process_id)
+ : coordinator_(coordinator),
+ render_process_id_(render_process_id),
+ binding_(this, std::move(request)) {
+ DCHECK(coordinator_);
}
-MemoryCoordinator::MemoryCoordinator() {}
+MemoryCoordinatorHandleImpl::~MemoryCoordinatorHandleImpl() {}
+
+void MemoryCoordinatorHandleImpl::AddChild(
+ mojom::ChildMemoryCoordinatorPtr child) {
+ DCHECK(!child_.is_bound());
+ child_ = std::move(child);
+ coordinator_->OnChildAdded(render_process_id_);
+}
+
+MemoryCoordinator::MemoryCoordinator()
+ : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()) {
+}
MemoryCoordinator::~MemoryCoordinator() {}
@@ -49,7 +65,8 @@ void MemoryCoordinator::CreateHandle(
int render_process_id,
mojom::MemoryCoordinatorHandleRequest request) {
std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
- new MemoryCoordinatorHandleImpl(std::move(request)));
+ new MemoryCoordinatorHandleImpl(std::move(request), this,
+ render_process_id));
handle->binding().set_connection_error_handler(
base::Bind(&MemoryCoordinator::OnConnectionError, base::Unretained(this),
render_process_id));
@@ -60,8 +77,8 @@ size_t MemoryCoordinator::NumChildrenForTesting() {
return children_.size();
}
-bool MemoryCoordinator::SetMemoryState(int render_process_id,
- mojom::MemoryState memory_state) {
+bool MemoryCoordinator::SetChildMemoryState(int render_process_id,
+ mojom::MemoryState memory_state) {
// Can't set an invalid memory state.
if (memory_state == mojom::MemoryState::UNKNOWN)
return false;
@@ -71,17 +88,31 @@ bool MemoryCoordinator::SetMemoryState(int render_process_id,
if (iter == children_.end())
return false;
+ // Can't send a message to a child that isn't bound.
+ if (!iter->second.handle->child().is_bound())
+ return false;
+
// A nop doesn't need to be sent, but is considered successful.
if (iter->second.memory_state == memory_state)
return true;
+ // Can't throttle the given renderer.
+ if (memory_state == mojom::MemoryState::THROTTLED &&
+ !CanThrottleRenderer(render_process_id))
+ return false;
+
+ // Can't suspend the given renderer.
+ if (memory_state == mojom::MemoryState::SUSPENDED &&
+ !CanSuspendRenderer(render_process_id))
+ return false;
+
// Update the internal state and send the message.
iter->second.memory_state = memory_state;
iter->second.handle->child()->OnStateChange(memory_state);
return true;
}
-mojom::MemoryState MemoryCoordinator::GetMemoryState(
+mojom::MemoryState MemoryCoordinator::GetChildMemoryState(
int render_process_id) const {
auto iter = children_.find(render_process_id);
if (iter == children_.end())
@@ -89,12 +120,40 @@ mojom::MemoryState MemoryCoordinator::GetMemoryState(
return iter->second.memory_state;
}
+void MemoryCoordinator::RecordMemoryPressure(
+ base::MemoryPressureMonitor::MemoryPressureLevel level) {
+ int state = static_cast<int>(GetCurrentMemoryState());
+ switch (level) {
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Memory.Coordinator.StateOnModerateNotificationReceived",
+ state, base::kMemoryStateMax);
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Memory.Coordinator.StateOnCriticalNotificationReceived",
+ state, base::kMemoryStateMax);
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+ NOTREACHED();
+ }
+}
+
+base::MemoryState MemoryCoordinator::GetCurrentMemoryState() const {
+ return base::MemoryState::UNKNOWN;
+}
+
+void MemoryCoordinator::SetCurrentMemoryStateForTesting(
+ base::MemoryState memory_state) {
+}
+
void MemoryCoordinator::AddChildForTesting(
int dummy_render_process_id, mojom::ChildMemoryCoordinatorPtr child) {
mojom::MemoryCoordinatorHandlePtr mch;
auto request = mojo::GetProxy(&mch);
std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
- new MemoryCoordinatorHandleImpl(std::move(request)));
+ new MemoryCoordinatorHandleImpl(std::move(request), this,
+ dummy_render_process_id));
handle->AddChild(std::move(child));
CreateChildInfoMapEntry(dummy_render_process_id, std::move(handle));
}
@@ -103,6 +162,26 @@ void MemoryCoordinator::OnConnectionError(int render_process_id) {
children_.erase(render_process_id);
}
+bool MemoryCoordinator::CanThrottleRenderer(int render_process_id) {
+ // If there is no delegate (i.e. tests), renderers are always throttleable.
+ // TODO(bashi): We check |delegate_| to avoid calling FromID() on a
+ // wrong thread in tests. Figure out a better way to handle tests.
+ if (!delegate_)
+ return true;
+ auto* render_process_host = RenderProcessHost::FromID(render_process_id);
+ return render_process_host->IsProcessBackgrounded();
+}
+
+bool MemoryCoordinator::CanSuspendRenderer(int render_process_id) {
+ // If there is no delegate (i.e. tests), renderers are always suspendable.
+ if (!delegate_)
+ return true;
+ auto* render_process_host = RenderProcessHost::FromID(render_process_id);
+ if (!render_process_host->IsProcessBackgrounded())
+ return false;
+ return delegate_->CanSuspendBackgroundedRenderer(render_process_id);
+}
+
void MemoryCoordinator::CreateChildInfoMapEntry(
int render_process_id,
std::unique_ptr<MemoryCoordinatorHandleImpl> handle) {
diff --git a/chromium/content/browser/memory/memory_coordinator.h b/chromium/content/browser/memory/memory_coordinator.h
index f674ef5b48c..7d2cbd76361 100644
--- a/chromium/content/browser/memory/memory_coordinator.h
+++ b/chromium/content/browser/memory/memory_coordinator.h
@@ -6,10 +6,11 @@
#define CONTENT_BROWSER_MEMORY_MEMORY_COORDINATOR_H_
#include "base/memory/memory_coordinator_client_registry.h"
-#include "base/memory/singleton.h"
+#include "base/memory/memory_pressure_monitor.h"
#include "base/process/process_handle.h"
#include "content/common/content_export.h"
#include "content/common/memory_coordinator.mojom.h"
+#include "content/public/browser/memory_coordinator_delegate.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace content {
@@ -24,11 +25,15 @@ class MemoryCoordinatorHandleImpl;
// child processes based on its best knowledge of the memory usage.
class CONTENT_EXPORT MemoryCoordinator {
public:
- ~MemoryCoordinator();
+ virtual ~MemoryCoordinator();
// Singleton factory/accessor.
static MemoryCoordinator* GetInstance();
+ // Starts monitoring memory usage. After calling this method, memory
+ // coordinator will start dispatching state changes.
+ virtual void Start() {}
+
// Creates a handle to the provided child process.
void CreateHandle(int render_process_id,
mojom::MemoryCoordinatorHandleRequest request);
@@ -39,12 +44,23 @@ class CONTENT_EXPORT MemoryCoordinator {
// Dispatches a memory state change to the provided process. Returns true if
// the process is tracked by this coordinator and successfully dispatches,
// returns false otherwise.
- bool SetMemoryState(
+ bool SetChildMemoryState(
int render_process_id, mojom::MemoryState memory_state);
// Returns the memory state of the specified render process. Returns UNKNOWN
// if the process is not tracked by this coordinator.
- mojom::MemoryState GetMemoryState(int render_process_id) const;
+ mojom::MemoryState GetChildMemoryState(int render_process_id) const;
+
+ // Records memory pressure notifications. Called by MemoryPressureMonitor.
+ // TODO(bashi): Remove this when MemoryPressureMonitor is retired.
+ void RecordMemoryPressure(
+ base::MemoryPressureMonitor::MemoryPressureLevel level);
+
+ // Called when ChildMemoryCoordinator calls AddChild().
+ virtual void OnChildAdded(int render_process_id) {}
+
+ virtual base::MemoryState GetCurrentMemoryState() const;
+ virtual void SetCurrentMemoryStateForTesting(base::MemoryState memory_state);
protected:
// Constructor. Protected as this is a singleton, but accessible for
@@ -59,13 +75,11 @@ class CONTENT_EXPORT MemoryCoordinator {
// for testing.
void OnConnectionError(int render_process_id);
- private:
- friend struct base::DefaultSingletonTraits<MemoryCoordinator>;
+ // Returns true when a given renderer can be throttled.
+ bool CanThrottleRenderer(int render_process_id);
- // Helper function of CreateHandle and AddChildForTesting.
- void CreateChildInfoMapEntry(
- int render_process_id,
- std::unique_ptr<MemoryCoordinatorHandleImpl> handle);
+ // Returns true when a given renderer can be suspended.
+ bool CanSuspendRenderer(int render_process_id);
// Stores information about any known child processes.
struct ChildInfo {
@@ -81,11 +95,21 @@ class CONTENT_EXPORT MemoryCoordinator {
// A map from process ID (RenderProcessHost::GetID()) to child process info.
using ChildInfoMap = std::map<int, ChildInfo>;
+ ChildInfoMap& children() { return children_; }
+
+private:
+ // Helper function of CreateHandle and AddChildForTesting.
+ void CreateChildInfoMapEntry(
+ int render_process_id,
+ std::unique_ptr<MemoryCoordinatorHandleImpl> handle);
+
// Tracks child processes. An entry is added when a renderer connects to
// MemoryCoordinator and removed automatically when an underlying binding is
// disconnected.
ChildInfoMap children_;
+ std::unique_ptr<MemoryCoordinatorDelegate> delegate_;
+
DISALLOW_COPY_AND_ASSIGN(MemoryCoordinator);
};
diff --git a/chromium/content/browser/memory/memory_coordinator_browsertest.cc b/chromium/content/browser/memory/memory_coordinator_browsertest.cc
index 03c3f4ad380..df22a9c4936 100644
--- a/chromium/content/browser/memory/memory_coordinator_browsertest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_browsertest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "content/browser/memory/memory_coordinator.h"
+
+#include "base/test/scoped_feature_list.h"
#include "content/browser/browser_main_loop.h"
#include "content/public/common/content_features.h"
#include "content/public/test/content_browser_test.h"
@@ -10,32 +12,28 @@
namespace content {
-namespace {
-
-void EnableForTesting() {
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(features::kMemoryCoordinator.name,
- "");
- base::FeatureList::SetInstance(std::move(feature_list));
-}
-
-} // namespace
-
class MemoryCoordinatorTest : public ContentBrowserTest {
public:
MemoryCoordinatorTest() {}
void SetUp() override {
- EnableForTesting();
+ scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator);
ContentBrowserTest::SetUp();
}
private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorTest);
};
-IN_PROC_BROWSER_TEST_F(MemoryCoordinatorTest, HandleAdded) {
+// TODO(bashi): Enable this test on macos when MemoryMonitorMac is implemented.
+#if defined(OS_MACOSX)
+#define MAYBE_HandleAdded DISABLED_HandleAdded
+#else
+#define MAYBE_HandleAdded HandleAdded
+#endif
+IN_PROC_BROWSER_TEST_F(MemoryCoordinatorTest, MAYBE_HandleAdded) {
GURL url = GetTestUrl("", "simple_page.html");
NavigateToURL(shell(), url);
EXPECT_EQ(1u, MemoryCoordinator::GetInstance()->NumChildrenForTesting());
diff --git a/chromium/content/browser/memory/memory_coordinator_impl.cc b/chromium/content/browser/memory/memory_coordinator_impl.cc
new file mode 100644
index 00000000000..c5bf7f1e8af
--- /dev/null
+++ b/chromium/content/browser/memory/memory_coordinator_impl.cc
@@ -0,0 +1,330 @@
+// 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/memory/memory_coordinator_impl.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/process/process_metrics.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/memory/memory_monitor.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/common/content_features.h"
+
+namespace content {
+
+namespace {
+
+// A expected renderer size. These values come from the median of appropriate
+// UMA stats.
+#if defined(OS_ANDROID) || defined(OS_IOS)
+const int kDefaultExpectedRendererSizeMB = 40;
+#elif defined(OS_WIN)
+const int kDefaultExpectedRendererSizeMB = 70;
+#else // Mac, Linux, and ChromeOS
+const int kDefaultExpectedRendererSizeMB = 120;
+#endif
+
+// Default values for parameters to determine the global state.
+const int kDefaultNewRenderersUntilThrottled = 4;
+const int kDefaultNewRenderersUntilSuspended = 2;
+const int kDefaultNewRenderersBackToNormal = 5;
+const int kDefaultNewRenderersBackToThrottled = 3;
+const int kDefaultMinimumTransitionPeriodSeconds = 30;
+const int kDefaultMonitoringIntervalSeconds = 5;
+
+mojom::MemoryState ToMojomMemoryState(base::MemoryState state) {
+ switch (state) {
+ case base::MemoryState::UNKNOWN:
+ return mojom::MemoryState::UNKNOWN;
+ case base::MemoryState::NORMAL:
+ return mojom::MemoryState::NORMAL;
+ case base::MemoryState::THROTTLED:
+ return mojom::MemoryState::THROTTLED;
+ case base::MemoryState::SUSPENDED:
+ return mojom::MemoryState::SUSPENDED;
+ default:
+ NOTREACHED();
+ return mojom::MemoryState::UNKNOWN;
+ }
+}
+
+void RecordMetricsOnStateChange(base::MemoryState prev_state,
+ base::MemoryState next_state,
+ base::TimeDelta duration,
+ size_t total_private_mb) {
+#define RECORD_METRICS(transition) \
+ UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Coordinator.TotalPrivate." transition, \
+ total_private_mb); \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Memory.Coordinator.StateDuration." transition, \
+ duration, base::TimeDelta::FromSeconds(30), \
+ base::TimeDelta::FromHours(24), 50);
+
+ if (prev_state == base::MemoryState::NORMAL) {
+ switch (next_state) {
+ case base::MemoryState::THROTTLED:
+ RECORD_METRICS("NormalToThrottled");
+ break;
+ case base::MemoryState::SUSPENDED:
+ RECORD_METRICS("NormalToSuspended");
+ break;
+ case base::MemoryState::UNKNOWN:
+ case base::MemoryState::NORMAL:
+ NOTREACHED();
+ break;
+ }
+ } else if (prev_state == base::MemoryState::THROTTLED) {
+ switch (next_state) {
+ case base::MemoryState::NORMAL:
+ RECORD_METRICS("ThrottledToNormal");
+ break;
+ case base::MemoryState::SUSPENDED:
+ RECORD_METRICS("ThrottledToSuspended");
+ break;
+ case base::MemoryState::UNKNOWN:
+ case base::MemoryState::THROTTLED:
+ NOTREACHED();
+ break;
+ }
+ } else if (prev_state == base::MemoryState::SUSPENDED) {
+ switch (next_state) {
+ case base::MemoryState::NORMAL:
+ RECORD_METRICS("SuspendedToNormal");
+ break;
+ case base::MemoryState::THROTTLED:
+ RECORD_METRICS("SuspendedToThrottled");
+ break;
+ case base::MemoryState::UNKNOWN:
+ case base::MemoryState::SUSPENDED:
+ NOTREACHED();
+ break;
+ }
+ } else {
+ NOTREACHED();
+ }
+#undef RECORD_METRICS
+}
+
+} // namespace
+
+// SingletonTraits for MemoryCoordinator. Returns MemoryCoordinatorImpl
+// as an actual instance.
+struct MemoryCoordinatorSingletonTraits
+ : public base::LeakySingletonTraits<MemoryCoordinator> {
+ static MemoryCoordinator* New() {
+ return new MemoryCoordinatorImpl(base::ThreadTaskRunnerHandle::Get(),
+ CreateMemoryMonitor());
+ }
+};
+
+// static
+MemoryCoordinator* MemoryCoordinator::GetInstance() {
+ if (!base::FeatureList::IsEnabled(features::kMemoryCoordinator))
+ return nullptr;
+ return base::Singleton<MemoryCoordinator,
+ MemoryCoordinatorSingletonTraits>::get();
+}
+
+MemoryCoordinatorImpl::MemoryCoordinatorImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<MemoryMonitor> memory_monitor)
+ : task_runner_(task_runner),
+ memory_monitor_(std::move(memory_monitor)),
+ weak_ptr_factory_(this) {
+ DCHECK(memory_monitor_.get());
+ update_state_callback_ = base::Bind(&MemoryCoordinatorImpl::UpdateState,
+ weak_ptr_factory_.GetWeakPtr());
+
+ // Set initial parameters for calculating the global state.
+ expected_renderer_size_ = kDefaultExpectedRendererSizeMB;
+ new_renderers_until_throttled_ = kDefaultNewRenderersUntilThrottled;
+ new_renderers_until_suspended_ = kDefaultNewRenderersUntilSuspended;
+ new_renderers_back_to_normal_ = kDefaultNewRenderersBackToNormal;
+ new_renderers_back_to_throttled_ = kDefaultNewRenderersBackToThrottled;
+ minimum_transition_period_ =
+ base::TimeDelta::FromSeconds(kDefaultMinimumTransitionPeriodSeconds);
+ monitoring_interval_ =
+ base::TimeDelta::FromSeconds(kDefaultMonitoringIntervalSeconds);
+}
+
+MemoryCoordinatorImpl::~MemoryCoordinatorImpl() {}
+
+void MemoryCoordinatorImpl::Start() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(last_state_change_.is_null());
+ DCHECK(ValidateParameters());
+
+ notification_registrar_.Add(
+ this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
+ NotificationService::AllBrowserContextsAndSources());
+ ScheduleUpdateState(base::TimeDelta());
+}
+
+void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) {
+ // Populate the global state as an initial state of a newly created process.
+ SetChildMemoryState(render_process_id, ToMojomMemoryState(current_state_));
+}
+
+base::MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const {
+ // SUSPENDED state may not make sense to the browser process. Use THROTTLED
+ // instead when the global state is SUSPENDED.
+ // TODO(bashi): Maybe worth considering another state for the browser.
+ return current_state_ == MemoryState::SUSPENDED ? MemoryState::THROTTLED
+ : current_state_;
+}
+
+void MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting(
+ base::MemoryState memory_state) {
+ // This changes the current state temporariy for testing. The state will be
+ // updated later by the task posted at ScheduleUpdateState.
+ DCHECK(memory_state != MemoryState::UNKNOWN);
+ base::MemoryState prev_state = current_state_;
+ current_state_ = memory_state;
+ if (prev_state != current_state_) {
+ NotifyStateToClients();
+ NotifyStateToChildren();
+ }
+}
+
+void MemoryCoordinatorImpl::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED);
+ RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr();
+ RenderProcessHost* process = render_widget_host->GetProcess();
+ if (!process)
+ return;
+ auto iter = children().find(process->GetID());
+ if (iter == children().end())
+ return;
+ bool is_visible = *Details<bool>(details).ptr();
+ // We don't throttle/suspend a visible renderer for now.
+ auto new_state = is_visible ? mojom::MemoryState::NORMAL
+ : ToMojomMemoryState(current_state_);
+ SetChildMemoryState(iter->first, new_state);
+}
+
+base::MemoryState MemoryCoordinatorImpl::CalculateNextState() {
+ using MemoryState = base::MemoryState;
+
+ int available = memory_monitor_->GetFreeMemoryUntilCriticalMB();
+
+ // TODO(chrisha): Move this histogram recording to a better place when
+ // https://codereview.chromium.org/2479673002/ is landed.
+ UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Coordinator.FreeMemoryUntilCritical",
+ available);
+
+ if (available <= 0)
+ return MemoryState::SUSPENDED;
+
+ int expected_renderer_count = available / expected_renderer_size_;
+
+ switch (current_state_) {
+ case MemoryState::NORMAL:
+ if (expected_renderer_count <= new_renderers_until_suspended_)
+ return MemoryState::SUSPENDED;
+ if (expected_renderer_count <= new_renderers_until_throttled_)
+ return MemoryState::THROTTLED;
+ return MemoryState::NORMAL;
+ case MemoryState::THROTTLED:
+ if (expected_renderer_count <= new_renderers_until_suspended_)
+ return MemoryState::SUSPENDED;
+ if (expected_renderer_count >= new_renderers_back_to_normal_)
+ return MemoryState::NORMAL;
+ return MemoryState::THROTTLED;
+ case MemoryState::SUSPENDED:
+ if (expected_renderer_count >= new_renderers_back_to_normal_)
+ return MemoryState::NORMAL;
+ if (expected_renderer_count >= new_renderers_back_to_throttled_)
+ return MemoryState::THROTTLED;
+ return MemoryState::SUSPENDED;
+ case MemoryState::UNKNOWN:
+ // Fall through
+ default:
+ NOTREACHED();
+ return MemoryState::UNKNOWN;
+ }
+}
+
+void MemoryCoordinatorImpl::UpdateState() {
+ base::TimeTicks prev_last_state_change = last_state_change_;
+ base::TimeTicks now = base::TimeTicks::Now();
+ MemoryState prev_state = current_state_;
+ MemoryState next_state = CalculateNextState();
+
+ if (last_state_change_.is_null() || current_state_ != next_state) {
+ current_state_ = next_state;
+ last_state_change_ = now;
+ }
+
+ if (next_state != prev_state) {
+ TRACE_EVENT2("memory-infra", "MemoryCoordinatorImpl::UpdateState",
+ "prev", MemoryStateToString(prev_state),
+ "next", MemoryStateToString(next_state));
+
+ RecordStateChange(prev_state, next_state, now - prev_last_state_change);
+ NotifyStateToClients();
+ NotifyStateToChildren();
+ ScheduleUpdateState(minimum_transition_period_);
+ } else {
+ ScheduleUpdateState(monitoring_interval_);
+ }
+}
+
+void MemoryCoordinatorImpl::NotifyStateToClients() {
+ auto state = GetCurrentMemoryState();
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state);
+}
+
+void MemoryCoordinatorImpl::NotifyStateToChildren() {
+ auto mojo_state = ToMojomMemoryState(current_state_);
+ // It's OK to call SetChildMemoryState() unconditionally because it checks
+ // whether this state transition is valid.
+ for (auto& iter : children())
+ SetChildMemoryState(iter.first, mojo_state);
+}
+
+void MemoryCoordinatorImpl::RecordStateChange(MemoryState prev_state,
+ MemoryState next_state,
+ base::TimeDelta duration) {
+ size_t total_private_kb = 0;
+
+ // TODO(bashi): On MacOS we can't get process metrics for child processes and
+ // therefore can't calculate the total private memory.
+#if !defined(OS_MACOSX)
+ auto browser_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics();
+ base::WorkingSetKBytes working_set;
+ browser_metrics->GetWorkingSetKBytes(&working_set);
+ total_private_kb += working_set.priv;
+
+ for (auto& iter : children()) {
+ auto* render_process_host = RenderProcessHost::FromID(iter.first);
+ DCHECK(render_process_host);
+ DCHECK(render_process_host->GetHandle() != base::kNullProcessHandle);
+ auto metrics = base::ProcessMetrics::CreateProcessMetrics(
+ render_process_host->GetHandle());
+ metrics->GetWorkingSetKBytes(&working_set);
+ total_private_kb += working_set.priv;
+ }
+#endif
+
+ RecordMetricsOnStateChange(prev_state, next_state, duration,
+ total_private_kb / 1024);
+}
+
+void MemoryCoordinatorImpl::ScheduleUpdateState(base::TimeDelta delta) {
+ task_runner_->PostDelayedTask(FROM_HERE, update_state_callback_, delta);
+}
+
+bool MemoryCoordinatorImpl::ValidateParameters() {
+ return (new_renderers_until_throttled_ > new_renderers_until_suspended_) &&
+ (new_renderers_back_to_normal_ > new_renderers_back_to_throttled_) &&
+ (new_renderers_back_to_normal_ > new_renderers_until_throttled_) &&
+ (new_renderers_back_to_throttled_ > new_renderers_until_suspended_);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/memory_coordinator_impl.h b/chromium/content/browser/memory/memory_coordinator_impl.h
new file mode 100644
index 00000000000..b86cc61be7a
--- /dev/null
+++ b/chromium/content/browser/memory/memory_coordinator_impl.h
@@ -0,0 +1,137 @@
+// 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_MEMORY_MEMORY_COORDINATOR_IMPL_H_
+#define CONTENT_BROWSER_MEMORY_MEMORY_COORDINATOR_IMPL_H_
+
+#include "base/callback.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
+#include "content/browser/memory/memory_coordinator.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+
+class MemoryMonitor;
+class MemoryCoordinatorImplTest;
+struct MemoryCoordinatorSingletonTraits;
+
+// MemoryCoordinatorImpl is an internal implementation of MemoryCoordinator
+// which uses a heuristic to determine a single global memory state.
+// In the current implementation browser process and renderer processes share
+// the global state; the memory coordinator will notify the global state to
+// all background renderers if the state has changed.
+//
+// State calculation:
+// MemoryCoordinatorImpl uses followings to determine the global state:
+// * Compute "number of renderers which can be created until the system will
+// be in a critical state". Call this N.
+// (See memory_monitor.h for the definition of "critical")
+// * Covert N to a memory state using some thresholds/hysteresis for each state.
+// Once a state is changed to a limited state, larger N will be needed to go
+// back to a relaxed state. (e.g. THROTTLED -> NORMAL)
+// * Once a state is changed, it remains the same for a certain period of time.
+class CONTENT_EXPORT MemoryCoordinatorImpl : public MemoryCoordinator,
+ public NotificationObserver,
+ public base::NonThreadSafe {
+ public:
+ MemoryCoordinatorImpl(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::unique_ptr<MemoryMonitor> monitor);
+ ~MemoryCoordinatorImpl() override;
+
+ // MemoryCoordinator implementations:
+ void Start() override;
+ void OnChildAdded(int render_process_id) override;
+
+ MemoryMonitor* memory_monitor() { return memory_monitor_.get(); }
+
+ base::MemoryState GetCurrentMemoryState() const override;
+ void SetCurrentMemoryStateForTesting(base::MemoryState memory_state) override;
+
+ // NotificationObserver implementation:
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(MemoryCoordinatorImplTest, CalculateNextState);
+ FRIEND_TEST_ALL_PREFIXES(MemoryCoordinatorImplTest, UpdateState);
+ FRIEND_TEST_ALL_PREFIXES(MemoryCoordinatorImplTest, SetMemoryStateForTesting);
+
+ friend struct MemoryCoordinatorSingletonTraits;
+
+ using MemoryState = base::MemoryState;
+
+ // Calculates the next global state from the amount of free memory using
+ // a heuristic.
+ MemoryState CalculateNextState();
+
+ // Updates the global state and notifies state changes to clients (lives in
+ // the browser) and child processes (renderers) if necessary.
+ void UpdateState();
+
+ // Notifies a state change to in-process clients.
+ void NotifyStateToClients();
+
+ // Notifies a state change to child processes.
+ void NotifyStateToChildren();
+
+ // Records metrics. This is called when the global state is changed.
+ void RecordStateChange(MemoryState prev_state,
+ MemoryState next_state,
+ base::TimeDelta duration);
+
+ // Schedules a task to update the global state. The task will be executed
+ // after |delay| has passed.
+ void ScheduleUpdateState(base::TimeDelta delay);
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ NotificationRegistrar notification_registrar_;
+ std::unique_ptr<MemoryMonitor> memory_monitor_;
+ base::Closure update_state_callback_;
+ base::MemoryState current_state_ = MemoryState::NORMAL;
+ base::TimeTicks last_state_change_;
+
+ // Validates parameters defined below.
+ bool ValidateParameters();
+
+ // Parameters to control the heuristic.
+
+ // The median size of a renderer on the current platform. This is used to
+ // convert the amount of free memory to an expected number of new renderers
+ // that could be started before hitting critical memory pressure.
+ int expected_renderer_size_;
+ // When in a NORMAL state and the potential number of new renderers drops
+ // below this level, the coordinator will transition to a THROTTLED state.
+ int new_renderers_until_throttled_;
+ // When in a NORMAL/THROTTLED state and the potential number of new renderers
+ // drops below this level, the coordinator will transition to a SUSPENDED
+ // state.
+ int new_renderers_until_suspended_;
+ // When in a THROTTLED/SUSPENDED state and the potential number of new
+ // renderers rises above this level, the coordinator will transition to a
+ // NORMAL state.
+ int new_renderers_back_to_normal_;
+ // When in a SUSPENDED state and the potential number of new renderers rises
+ // above this level, the coordinator will transition to a SUSPENDED state.
+ int new_renderers_back_to_throttled_;
+ // The memory coordinator stays in the same state at least this duration even
+ // when there are considerable changes in the amount of free memory to prevent
+ // thrashing.
+ base::TimeDelta minimum_transition_period_;
+ // The interval of checking the amount of free memory.
+ base::TimeDelta monitoring_interval_;
+
+ base::WeakPtrFactory<MemoryCoordinatorImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEMORY_MEMORY_COORDINATOR_IMPL_H_
diff --git a/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
new file mode 100644
index 00000000000..787636dbb43
--- /dev/null
+++ b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
@@ -0,0 +1,219 @@
+// 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/memory/memory_coordinator_impl.h"
+
+#include "base/memory/memory_coordinator_proxy.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/memory/memory_monitor.h"
+#include "content/public/common/content_features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient {
+ public:
+ void OnMemoryStateChange(base::MemoryState state) override {
+ is_called_ = true;
+ state_ = state;
+ }
+
+ bool is_called() { return is_called_; }
+ base::MemoryState state() { return state_; }
+
+ private:
+ bool is_called_ = false;
+ base::MemoryState state_ = base::MemoryState::NORMAL;
+};
+
+} // namespace
+
+class MockMemoryMonitor : public MemoryMonitor {
+ public:
+ MockMemoryMonitor() {}
+ ~MockMemoryMonitor() override {}
+
+ void SetFreeMemoryUntilCriticalMB(int free_memory) {
+ free_memory_ = free_memory;
+ }
+
+ // MemoryMonitor implementation
+ int GetFreeMemoryUntilCriticalMB() override { return free_memory_; }
+
+ private:
+ int free_memory_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor);
+};
+
+class MemoryCoordinatorImplTest : public testing::Test {
+ public:
+ void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator);
+
+ coordinator_.reset(new MemoryCoordinatorImpl(
+ message_loop_.task_runner(), base::WrapUnique(new MockMemoryMonitor)));
+
+ base::MemoryCoordinatorProxy::GetInstance()->
+ SetGetCurrentMemoryStateCallback(base::Bind(
+ &MemoryCoordinator::GetCurrentMemoryState,
+ base::Unretained(coordinator_.get())));
+ base::MemoryCoordinatorProxy::GetInstance()->
+ SetSetCurrentMemoryStateForTestingCallback(base::Bind(
+ &MemoryCoordinator::SetCurrentMemoryStateForTesting,
+ base::Unretained(coordinator_.get())));
+ }
+
+ MockMemoryMonitor* GetMockMemoryMonitor() {
+ return static_cast<MockMemoryMonitor*>(coordinator_->memory_monitor());
+ }
+
+ protected:
+ std::unique_ptr<MemoryCoordinatorImpl> coordinator_;
+ base::MessageLoop message_loop_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(MemoryCoordinatorImplTest, CalculateNextState) {
+ coordinator_->expected_renderer_size_ = 10;
+ coordinator_->new_renderers_until_throttled_ = 4;
+ coordinator_->new_renderers_until_suspended_ = 2;
+ coordinator_->new_renderers_back_to_normal_ = 5;
+ coordinator_->new_renderers_back_to_throttled_ = 3;
+ DCHECK(coordinator_->ValidateParameters());
+
+ // The default state is NORMAL.
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::NORMAL,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+
+ // Transitions from NORMAL
+ coordinator_->current_state_ = base::MemoryState::NORMAL;
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::NORMAL,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40);
+ EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(20);
+ EXPECT_EQ(base::MemoryState::SUSPENDED, coordinator_->CalculateNextState());
+
+ // Transitions from THROTTLED
+ coordinator_->current_state_ = base::MemoryState::THROTTLED;
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40);
+ EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(20);
+ EXPECT_EQ(base::MemoryState::SUSPENDED, coordinator_->CalculateNextState());
+
+ // Transitions from SUSPENDED
+ coordinator_->current_state_ = base::MemoryState::SUSPENDED;
+ // GetCurrentMemoryState() returns THROTTLED state for the browser process
+ // when the global state is SUSPENDED.
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(20);
+ EXPECT_EQ(base::MemoryState::SUSPENDED, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(30);
+ EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->CalculateNextState());
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->CalculateNextState());
+}
+
+TEST_F(MemoryCoordinatorImplTest, UpdateState) {
+ coordinator_->expected_renderer_size_ = 10;
+ coordinator_->new_renderers_until_throttled_ = 4;
+ coordinator_->new_renderers_until_suspended_ = 2;
+ coordinator_->new_renderers_back_to_normal_ = 5;
+ coordinator_->new_renderers_back_to_throttled_ = 3;
+ DCHECK(coordinator_->ValidateParameters());
+
+ {
+ // Transition happens (NORMAL -> THROTTLED).
+ MockMemoryCoordinatorClient client;
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
+ coordinator_->current_state_ = base::MemoryState::NORMAL;
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40);
+ coordinator_->UpdateState();
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ EXPECT_TRUE(client.is_called());
+ EXPECT_EQ(base::MemoryState::THROTTLED, client.state());
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
+ }
+
+ {
+ // No transtion (NORMAL -> NORMAL). OnStateChange shouldn't be called.
+ MockMemoryCoordinatorClient client;
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
+ coordinator_->current_state_ = base::MemoryState::NORMAL;
+ GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
+ coordinator_->UpdateState();
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ EXPECT_FALSE(client.is_called());
+ EXPECT_EQ(base::MemoryState::NORMAL, client.state());
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
+ }
+}
+
+TEST_F(MemoryCoordinatorImplTest, SetMemoryStateForTesting) {
+ coordinator_->expected_renderer_size_ = 10;
+ coordinator_->new_renderers_until_throttled_ = 4;
+ coordinator_->new_renderers_until_suspended_ = 2;
+ coordinator_->new_renderers_back_to_normal_ = 5;
+ coordinator_->new_renderers_back_to_throttled_ = 3;
+ DCHECK(coordinator_->ValidateParameters());
+
+ MockMemoryCoordinatorClient client;
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
+ EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::NORMAL,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::NORMAL, client.state());
+
+ base::MemoryCoordinatorProxy::GetInstance()->SetCurrentMemoryStateForTesting(
+ base::MemoryState::SUSPENDED);
+ // GetCurrentMemoryState() returns THROTTLED state for the browser process
+ // when the global state is SUSPENDED.
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+
+ base::MemoryCoordinatorProxy::GetInstance()->SetCurrentMemoryStateForTesting(
+ base::MemoryState::THROTTLED);
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ coordinator_->GetCurrentMemoryState());
+ EXPECT_EQ(base::MemoryState::THROTTLED,
+ base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState());
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ EXPECT_TRUE(client.is_called());
+ EXPECT_EQ(base::MemoryState::THROTTLED, client.state());
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/memory_coordinator_unittest.cc b/chromium/content/browser/memory/memory_coordinator_unittest.cc
index c62232f1a14..d6cf7df5ddf 100644
--- a/chromium/content/browser/memory/memory_coordinator_unittest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_unittest.cc
@@ -59,7 +59,7 @@ class TestMemoryCoordinator : public MemoryCoordinator {
};
TestMemoryCoordinator() {}
- ~TestMemoryCoordinator() {}
+ ~TestMemoryCoordinator() override {}
using MemoryCoordinator::OnConnectionError;
@@ -72,9 +72,9 @@ class TestMemoryCoordinator : public MemoryCoordinator {
}
// Wrapper of MemoryCoordinator::SetMemoryState that also calls RunUntilIdle.
- bool SetMemoryState(
+ bool SetChildMemoryState(
int render_process_id, mojom::MemoryState memory_state) {
- bool result = MemoryCoordinator::SetMemoryState(
+ bool result = MemoryCoordinator::SetChildMemoryState(
render_process_id, memory_state);
RunUntilIdle();
return result;
@@ -102,7 +102,7 @@ TEST_F(MemoryCoordinatorTest, SetMemoryStateFailsInvalidState) {
TestMemoryCoordinator mc;
auto cmc1 = mc.CreateChildMemoryCoordinator(1);
- EXPECT_FALSE(mc.SetMemoryState(1, mojom::MemoryState::UNKNOWN));
+ EXPECT_FALSE(mc.SetChildMemoryState(1, mojom::MemoryState::UNKNOWN));
EXPECT_EQ(0, cmc1->on_state_change_calls());
}
@@ -110,7 +110,7 @@ TEST_F(MemoryCoordinatorTest, SetMemoryStateFailsInvalidRenderer) {
TestMemoryCoordinator mc;
auto cmc1 = mc.CreateChildMemoryCoordinator(1);
- EXPECT_FALSE(mc.SetMemoryState(2, mojom::MemoryState::THROTTLED));
+ EXPECT_FALSE(mc.SetChildMemoryState(2, mojom::MemoryState::THROTTLED));
EXPECT_EQ(0, cmc1->on_state_change_calls());
}
@@ -118,7 +118,7 @@ TEST_F(MemoryCoordinatorTest, SetMemoryStateNotDeliveredNop) {
TestMemoryCoordinator mc;
auto cmc1 = mc.CreateChildMemoryCoordinator(1);
- EXPECT_FALSE(mc.SetMemoryState(2, mojom::MemoryState::NORMAL));
+ EXPECT_FALSE(mc.SetChildMemoryState(2, mojom::MemoryState::NORMAL));
EXPECT_EQ(0, cmc1->on_state_change_calls());
}
@@ -127,11 +127,11 @@ TEST_F(MemoryCoordinatorTest, SetMemoryStateDelivered) {
auto cmc1 = mc.CreateChildMemoryCoordinator(1);
auto cmc2 = mc.CreateChildMemoryCoordinator(2);
- EXPECT_TRUE(mc.SetMemoryState(1, mojom::MemoryState::THROTTLED));
+ EXPECT_TRUE(mc.SetChildMemoryState(1, mojom::MemoryState::THROTTLED));
EXPECT_EQ(1, cmc1->on_state_change_calls());
EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc1->state());
- EXPECT_TRUE(mc.SetMemoryState(2, mojom::MemoryState::SUSPENDED));
+ EXPECT_TRUE(mc.SetChildMemoryState(2, mojom::MemoryState::SUSPENDED));
EXPECT_EQ(1, cmc2->on_state_change_calls());
EXPECT_EQ(mojom::MemoryState::SUSPENDED, cmc2->state());
}
diff --git a/chromium/content/browser/memory/memory_monitor.cc b/chromium/content/browser/memory/memory_monitor.cc
index 5e67c9cb5b3..a9e168457df 100644
--- a/chromium/content/browser/memory/memory_monitor.cc
+++ b/chromium/content/browser/memory/memory_monitor.cc
@@ -22,4 +22,12 @@ void MemoryMonitorDelegate::GetSystemMemoryInfo(
base::GetSystemMemoryInfo(mem_info);
}
+#if defined(OS_MACOSX)
+// TODO(bashi,bcwhite): Remove when memory monitor for mac is available.
+std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
+ NOTREACHED();
+ return std::unique_ptr<MemoryMonitor>();
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/memory/memory_monitor_android.cc b/chromium/content/browser/memory/memory_monitor_android.cc
index 70c1e6dc4ca..ba73f7363bf 100644
--- a/chromium/content/browser/memory/memory_monitor_android.cc
+++ b/chromium/content/browser/memory/memory_monitor_android.cc
@@ -7,12 +7,22 @@
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "content/browser/memory/memory_coordinator.h"
#include "jni/MemoryMonitorAndroid_jni.h"
namespace content {
namespace {
+
const size_t kMBShift = 20;
+
+void RegisterComponentCallbacks() {
+ Java_MemoryMonitorAndroid_registerComponentCallbacks(
+ base::android::AttachCurrentThread(),
+ base::android::GetApplicationContext());
+}
+
}
// An implementation of MemoryMonitorAndroid::Delegate using the Android APIs.
@@ -54,6 +64,34 @@ static void GetMemoryInfoCallback(
info->total_mem = total_mem;
}
+// The maximum level of onTrimMemory (TRIM_MEMORY_COMPLETE).
+const int kTrimMemoryLevelMax = 0x80;
+
+// Called by JNI.
+static void OnTrimMemory(JNIEnv* env,
+ const base::android::JavaParamRef<jclass>& jcaller,
+ jint level) {
+ DCHECK(level >= 0 && level <= kTrimMemoryLevelMax);
+ auto state = MemoryCoordinator::GetInstance()->GetCurrentMemoryState();
+ switch (state) {
+ case base::MemoryState::NORMAL:
+ UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Normal",
+ level, kTrimMemoryLevelMax);
+ break;
+ case base::MemoryState::THROTTLED:
+ UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Throttled",
+ level, kTrimMemoryLevelMax);
+ break;
+ case base::MemoryState::SUSPENDED:
+ UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Suspended",
+ level, kTrimMemoryLevelMax);
+ break;
+ case base::MemoryState::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+}
+
// static
std::unique_ptr<MemoryMonitorAndroid> MemoryMonitorAndroid::Create() {
auto delegate = base::WrapUnique(new MemoryMonitorAndroidDelegateImpl);
@@ -68,6 +106,7 @@ bool MemoryMonitorAndroid::Register(JNIEnv* env) {
MemoryMonitorAndroid::MemoryMonitorAndroid(std::unique_ptr<Delegate> delegate)
: delegate_(std::move(delegate)) {
DCHECK(delegate_.get());
+ RegisterComponentCallbacks();
}
MemoryMonitorAndroid::~MemoryMonitorAndroid() {}
diff --git a/chromium/content/browser/memory/memory_monitor_linux.cc b/chromium/content/browser/memory/memory_monitor_linux.cc
index 08cf8027b03..68421c8c4e1 100644
--- a/chromium/content/browser/memory/memory_monitor_linux.cc
+++ b/chromium/content/browser/memory/memory_monitor_linux.cc
@@ -33,9 +33,11 @@ int MemoryMonitorLinux::GetFreeMemoryUntilCriticalMB() {
if (mem_info.available > 0)
return mem_info.available >> kShiftKiBtoMiB;
- // If there is no "available" value, guess at it based on free memory and
- // what the OS can easily discard.
- return (mem_info.free + mem_info.buffers + mem_info.cached) >> kShiftKiBtoMiB;
+ // If there is no "available" value, guess at it based on free memory.
+ // Though there will be easily discardable memory (buffers and caches), we
+ // don't count them because discarding them will affect the overall
+ // performance of the OS.
+ return mem_info.free >> kShiftKiBtoMiB;
}
// static
diff --git a/chromium/content/browser/memory/memory_monitor_linux_unittest.cc b/chromium/content/browser/memory/memory_monitor_linux_unittest.cc
index 3aa7306417f..7914b0f358f 100644
--- a/chromium/content/browser/memory/memory_monitor_linux_unittest.cc
+++ b/chromium/content/browser/memory/memory_monitor_linux_unittest.cc
@@ -64,7 +64,7 @@ TEST_F(MemoryMonitorLinuxTest, GetFreeMemoryUntilCriticalMB) {
delegate_.ResetCalls();
delegate_.SetFreeMemoryKB(64 * kKBperMB, 32 * kKBperMB, 16 * kKBperMB);
- EXPECT_EQ(112, monitor_->GetFreeMemoryUntilCriticalMB());
+ EXPECT_EQ(64, monitor_->GetFreeMemoryUntilCriticalMB());
EXPECT_EQ(1U, delegate_.calls());
delegate_.ResetCalls();
diff --git a/chromium/content/browser/memory/memory_pressure_controller_impl.cc b/chromium/content/browser/memory/memory_pressure_controller_impl.cc
index 1026783e468..13d5cfd2d37 100644
--- a/chromium/content/browser/memory/memory_pressure_controller_impl.cc
+++ b/chromium/content/browser/memory/memory_pressure_controller_impl.cc
@@ -39,7 +39,8 @@ void MemoryPressureControllerImpl::OnMemoryMessageFilterRemoved(
// Remove the message filter from the set of all memory message filters,
// ensuring that it was there beforehand.
auto it = memory_message_filters_.find(filter->process_host());
- DCHECK(it != memory_message_filters_.end());
+ if (it == memory_message_filters_.end())
+ return;
DCHECK_EQ(filter, it->second);
memory_message_filters_.erase(it);
}
diff --git a/chromium/content/browser/message_port_provider.cc b/chromium/content/browser/message_port_provider.cc
index b2a44635c16..aa6ae9567bf 100644
--- a/chromium/content/browser/message_port_provider.cc
+++ b/chromium/content/browser/message_port_provider.cc
@@ -13,6 +13,10 @@
#include "content/common/frame_messages.h"
#include "content/public/browser/message_port_delegate.h"
+#if defined(OS_ANDROID)
+#include "content/browser/android/app_web_message_port_service_impl.h"
+#endif
+
namespace content {
// static
@@ -24,6 +28,13 @@ void MessagePortProvider::PostMessageToFrame(
const std::vector<int>& ports) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if defined(OS_ANDROID)
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&content::AppWebMessagePortServiceImpl::RemoveSentPorts,
+ base::Unretained(AppWebMessagePortServiceImpl::GetInstance()),
+ ports));
+#endif
FrameMsg_PostMessage_Params params;
params.is_data_raw_string = true;
params.data = data;
@@ -41,68 +52,11 @@ void MessagePortProvider::PostMessageToFrame(
web_contents->GetMainFrame()->GetRoutingID(), params));
}
+#if defined(OS_ANDROID)
// static
-void MessagePortProvider::CreateMessageChannel(MessagePortDelegate* delegate,
- int* port1,
- int* port2) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- *port1 = 0;
- *port2 = 0;
- MessagePortService* msp = MessagePortService::GetInstance();
- msp->Create(MSG_ROUTING_NONE, delegate, port1);
- msp->Create(MSG_ROUTING_NONE, delegate, port2);
- // Update the routing number of the message ports to be equal to the message
- // port numbers.
- msp->UpdateMessagePort(*port1, delegate, *port1);
- msp->UpdateMessagePort(*port2, delegate, *port2);
- msp->Entangle(*port1, *port2);
- msp->Entangle(*port2, *port1);
-}
-
-// static
-void MessagePortProvider::PostMessageToPort(
- int sender_port_id,
- const base::string16& message,
- const std::vector<int>& sent_ports) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MessagePortService* msp = MessagePortService::GetInstance();
- msp->PostMessage(sender_port_id, message, sent_ports);
-}
-
-// static
-void MessagePortProvider::ClosePort(int message_port_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MessagePortService* msp = MessagePortService::GetInstance();
- msp->ClosePort(message_port_id);
-}
-
-// static
-void MessagePortProvider::HoldMessages(int message_port_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MessagePortService* msp = MessagePortService::GetInstance();
- msp->HoldMessages(message_port_id);
-}
-
-// static
-void MessagePortProvider::ReleaseMessages(int message_port_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MessagePortService* msp = MessagePortService::GetInstance();
- msp->ReleaseMessages(message_port_id);
-}
-
-// static
-void MessagePortProvider::OnMessagePortDelegateClosing(
- MessagePortDelegate* delegate) {
- MessagePortService::GetInstance()->OnMessagePortDelegateClosing(delegate);
-}
-
-// static
-void MessagePortProvider::UpdateMessagePort(int message_port_id,
- MessagePortDelegate* delegate) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MessagePortService::GetInstance()->UpdateMessagePort(message_port_id,
- delegate,
- message_port_id);
+AppWebMessagePortService* MessagePortProvider::GetAppWebMessagePortService() {
+ return AppWebMessagePortServiceImpl::GetInstance();
}
+#endif
} // namespace content
diff --git a/chromium/content/browser/message_port_provider_browsertest.cc b/chromium/content/browser/message_port_provider_browsertest.cc
index bac99abaa98..6e7f8951947 100644
--- a/chromium/content/browser/message_port_provider_browsertest.cc
+++ b/chromium/content/browser/message_port_provider_browsertest.cc
@@ -87,59 +87,4 @@ IN_PROC_BROWSER_TEST_F(MessagePortProviderBrowserTest, PostMessage) {
EXPECT_EQ(message, title_watcher.WaitAndGetTitle());
}
-namespace {
-
-void VerifyCreateChannelOnIOThread(base::WaitableEvent* event) {
-
- const base::char16 MESSAGE1[] = { 0x1000, 0 };
- const base::char16 MESSAGE2[] = { 0x1001, 0 };
-
- MockMessagePortDelegate delegate;
- int port1;
- int port2;
-
- MessagePortProvider::CreateMessageChannel(&delegate, &port1, &port2);
- MessagePortService* service = MessagePortService::GetInstance();
- // Send a message to port1 transferring no ports.
- std::vector<int> sent_ports;
- service->PostMessage(port1, base::string16(MESSAGE1), sent_ports);
- // Verify that message is received
- const MockMessagePortDelegate::Messages& received =
- delegate.getReceivedMessages();
- EXPECT_EQ(received.size(), 1u);
- // Verify that message sent to port1 is received by entangled port, which is
- // port2.
- EXPECT_EQ(received[0].route_id, port2);
- EXPECT_EQ(received[0].data, MESSAGE1);
- EXPECT_EQ(received[0].sent_ports.size(), 0u);
-
- // Create a new channel, and transfer one of its ports to port2, making sure
- // the transferred port is received.
- int port3;
- int port4;
- MessagePortProvider::CreateMessageChannel(&delegate, &port3, &port4);
- sent_ports.push_back(port3);
- service->PostMessage(port1, base::string16(MESSAGE2), sent_ports);
- EXPECT_EQ(received.size(), 2u);
- EXPECT_EQ(received[1].route_id, port2);
- EXPECT_EQ(received[1].data, MESSAGE2);
- EXPECT_EQ(received[1].sent_ports.size(), 1u);
- EXPECT_EQ(received[1].sent_ports[0], port3);
-
- event->Signal();
-}
-
-} // namespace
-
-// Verify that a message channel can be created and used for exchanging
-// messages.
-IN_PROC_BROWSER_TEST_F(MessagePortProviderBrowserTest, CreateChannel) {
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&VerifyCreateChannelOnIOThread, &event));
- event.Wait();
-}
-
} // namespace content
diff --git a/chromium/content/browser/mojo_sandbox_browsertest.cc b/chromium/content/browser/mojo_sandbox_browsertest.cc
index 4a1ef7e68b7..f3eddd9ad57 100644
--- a/chromium/content/browser/mojo_sandbox_browsertest.cc
+++ b/chromium/content/browser/mojo_sandbox_browsertest.cc
@@ -14,7 +14,7 @@
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/test_service.mojom.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
namespace content {
namespace {
diff --git a/chromium/content/browser/net/browser_online_state_observer.cc b/chromium/content/browser/net/browser_online_state_observer.cc
index 9b457f9b75d..a2bbdfe804e 100644
--- a/chromium/content/browser/net/browser_online_state_observer.cc
+++ b/chromium/content/browser/net/browser_online_state_observer.cc
@@ -26,8 +26,8 @@ void BrowserOnlineStateObserver::OnMaxBandwidthChanged(
net::NetworkChangeNotifier::ConnectionType type) {
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->Send(
- new ViewMsg_NetworkConnectionChanged(type, max_bandwidth_mbps));
+ it.GetCurrentValue()->GetRendererInterface()->OnNetworkConnectionChanged(
+ type, max_bandwidth_mbps);
}
}
@@ -43,8 +43,8 @@ void BrowserOnlineStateObserver::Observe(
net::NetworkChangeNotifier::ConnectionType connection_type;
net::NetworkChangeNotifier::GetMaxBandwidthAndConnectionType(
&max_bandwidth_mbps, &connection_type);
- rph->Send(new ViewMsg_NetworkConnectionChanged(connection_type,
- max_bandwidth_mbps));
+ rph->GetRendererInterface()->OnNetworkConnectionChanged(
+ connection_type, max_bandwidth_mbps);
}
} // 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 28edfbf170f..b759c5b608c 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -97,14 +97,14 @@ void QuotaPolicyCookieStore::Flush(const base::Closure& callback) {
void QuotaPolicyCookieStore::OnLoad(
const LoadedCallback& loaded_callback,
- const std::vector<net::CanonicalCookie*>& cookies) {
- for (auto* cookie : cookies) {
+ std::vector<std::unique_ptr<net::CanonicalCookie>> cookies) {
+ for (const auto& cookie : cookies) {
net::SQLitePersistentCookieStore::CookieOrigin origin(
cookie->Domain(), cookie->IsSecure());
++cookies_per_origin_[origin];
}
- loaded_callback.Run(cookies);
+ loaded_callback.Run(std::move(cookies));
}
CookieStoreConfig::CookieStoreConfig()
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.h b/chromium/content/browser/net/quota_policy_cookie_store.h
index 6aee20f97de..25783cf4b74 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.h
+++ b/chromium/content/browser/net/quota_policy_cookie_store.h
@@ -20,14 +20,8 @@
class Task;
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-} // namespace base
-
namespace net {
class CanonicalCookie;
-class CookieCryptoDelegate;
} // namespace net
namespace storage {
@@ -68,7 +62,7 @@ class CONTENT_EXPORT QuotaPolicyCookieStore
// Called after cookies are loaded from the database. Calls |loaded_callback|
// when done.
void OnLoad(const LoadedCallback& loaded_callback,
- const std::vector<net::CanonicalCookie*>& cookies);
+ std::vector<std::unique_ptr<net::CanonicalCookie>> cookies);
// Map of (domain keys(eTLD+1), is secure cookie) to number of cookies in the
// database.
diff --git a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
index 436728eb383..707f85606ee 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
@@ -7,7 +7,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/sequenced_worker_pool.h"
@@ -31,7 +30,8 @@ const base::FilePath::CharType kTestCookiesFilename[] =
namespace content {
namespace {
-typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector;
+using CanonicalCookieVector =
+ std::vector<std::unique_ptr<net::CanonicalCookie>>;
class QuotaPolicyCookieStoreTest : public testing::Test {
public:
@@ -42,8 +42,8 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
destroy_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED) {}
- void OnLoaded(const CanonicalCookieVector& cookies) {
- cookies_ = cookies;
+ void OnLoaded(CanonicalCookieVector cookies) {
+ cookies_.swap(cookies);
loaded_event_.Signal();
}
@@ -52,7 +52,7 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
store_->Load(base::Bind(&QuotaPolicyCookieStoreTest::OnLoaded,
base::Unretained(this)));
loaded_event_.Wait();
- *cookies = cookies_;
+ cookies->swap(cookies_);
}
void ReleaseStore() {
@@ -148,12 +148,12 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPersistence) {
DestroyStore();
// Reload and test for persistence.
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(2U, cookies.size());
bool found_foo_cookie = false;
bool found_persistent_cookie = false;
- for (auto* cookie : cookies) {
+ for (const auto& cookie : cookies) {
if (cookie->Domain() == "foo.com")
found_foo_cookie = true;
else if (cookie->Domain() == "persistent.com")
@@ -168,10 +168,10 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPersistence) {
DestroyStore();
// Reload and check if the cookies have been removed.
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(0U, cookies.size());
- base::STLDeleteElements(&cookies);
+ cookies.clear();
}
// Test if data is stored as expected in the QuotaPolicy database.
@@ -199,7 +199,7 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPolicy) {
net::cookie_util::CookieOriginToURL("nonpersistent.com", false));
// Reload and test for persistence.
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(3U, cookies.size());
@@ -210,14 +210,14 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPolicy) {
// Now close the store, and "nonpersistent.com" should be deleted according to
// policy.
DestroyStore();
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(2U, cookies.size());
- for (auto* cookie : cookies) {
+ for (const auto& cookie : cookies) {
EXPECT_NE("nonpersistent.com", cookie->Domain());
}
- base::STLDeleteElements(&cookies);
+ cookies.clear();
}
TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
@@ -237,7 +237,7 @@ TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
net::cookie_util::CookieOriginToURL("nonpersistent.com", false));
// Reload and test for persistence
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(1U, cookies.size());
@@ -250,11 +250,11 @@ TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
// deleted.
store_->SetForceKeepSessionState();
DestroyStore();
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(nullptr, &cookies);
EXPECT_EQ(3U, cookies.size());
- base::STLDeleteElements(&cookies);
+ cookies.clear();
}
// Tests that the special storage policy is properly applied even when the store
@@ -280,11 +280,11 @@ TEST_F(QuotaPolicyCookieStoreTest, TestDestroyOnBackgroundThread) {
DestroyStoreOnBackgroundThread();
// Reload and test for persistence.
- base::STLDeleteElements(&cookies);
+ cookies.clear();
CreateAndLoad(storage_policy.get(), &cookies);
EXPECT_EQ(0U, cookies.size());
- base::STLDeleteElements(&cookies);
+ cookies.clear();
}
} // namespace
diff --git a/chromium/content/browser/net/view_blob_internals_job_factory.cc b/chromium/content/browser/net/view_blob_internals_job_factory.cc
index 2f00bededf4..409148f4054 100644
--- a/chromium/content/browser/net/view_blob_internals_job_factory.cc
+++ b/chromium/content/browser/net/view_blob_internals_job_factory.cc
@@ -15,7 +15,7 @@ namespace content {
// static.
bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) {
return url.SchemeIs(kChromeUIScheme) &&
- url.host() == kChromeUIBlobInternalsHost;
+ url.host_piece() == kChromeUIBlobInternalsHost;
}
// static.
diff --git a/chromium/content/browser/net/view_http_cache_job_factory.cc b/chromium/content/browser/net/view_http_cache_job_factory.cc
index 3bd1f2c3c0e..ca64341e0d5 100644
--- a/chromium/content/browser/net/view_http_cache_job_factory.cc
+++ b/chromium/content/browser/net/view_http_cache_job_factory.cc
@@ -194,7 +194,7 @@ void ViewHttpCacheJob::Core::OnIOComplete(int result) {
// Static.
bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
return url.SchemeIs(kChromeUIScheme) &&
- url.host() == kChromeUINetworkViewCacheHost;
+ url.host_piece() == kChromeUINetworkViewCacheHost;
}
// Static.
diff --git a/chromium/content/browser/notification_service_impl.cc b/chromium/content/browser/notification_service_impl.cc
index 27de8579fe8..b732ca7cf40 100644
--- a/chromium/content/browser/notification_service_impl.cc
+++ b/chromium/content/browser/notification_service_impl.cc
@@ -105,31 +105,27 @@ void NotificationServiceImpl::Notify(int type,
// Notify observers of all types and all sources
if (HasKey(observers_[NOTIFICATION_ALL], AllSources()) &&
source != AllSources()) {
- FOR_EACH_OBSERVER(NotificationObserver,
- *observers_[NOTIFICATION_ALL][AllSources().map_key()],
- Observe(type, source, details));
+ for (auto& observer : *observers_[NOTIFICATION_ALL][AllSources().map_key()])
+ observer.Observe(type, source, details);
}
// Notify observers of all types and the given source
if (HasKey(observers_[NOTIFICATION_ALL], source)) {
- FOR_EACH_OBSERVER(NotificationObserver,
- *observers_[NOTIFICATION_ALL][source.map_key()],
- Observe(type, source, details));
+ for (auto& observer : *observers_[NOTIFICATION_ALL][source.map_key()])
+ observer.Observe(type, source, details);
}
// Notify observers of the given type and all sources
if (HasKey(observers_[type], AllSources()) &&
source != AllSources()) {
- FOR_EACH_OBSERVER(NotificationObserver,
- *observers_[type][AllSources().map_key()],
- Observe(type, source, details));
+ for (auto& observer : *observers_[type][AllSources().map_key()])
+ observer.Observe(type, source, details);
}
// Notify observers of the given type and the given source
if (HasKey(observers_[type], source)) {
- FOR_EACH_OBSERVER(NotificationObserver,
- *observers_[type][source.map_key()],
- Observe(type, source, details));
+ for (auto& observer : *observers_[type][source.map_key()])
+ observer.Observe(type, source, details);
}
}
diff --git a/chromium/content/browser/notifications/notification_database.h b/chromium/content/browser/notifications/notification_database.h
index 2dbd13e1d38..e85594f0ee6 100644
--- a/chromium/content/browser/notifications/notification_database.h
+++ b/chromium/content/browser/notifications/notification_database.h
@@ -22,7 +22,6 @@ namespace leveldb {
class DB;
class Env;
class FilterPolicy;
-class WriteBatch;
}
namespace content {
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index 9eb1ade75ff..5f097bc0251 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -203,6 +203,7 @@ void DispatchNotificationClickEventOnWorker(
const scoped_refptr<ServiceWorkerVersion>& service_worker,
const NotificationDatabaseData& notification_database_data,
int action_index,
+ const base::NullableString16& reply,
const ServiceWorkerVersion::StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
int request_id = service_worker->StartRequest(
@@ -212,12 +213,13 @@ void DispatchNotificationClickEventOnWorker(
request_id,
ServiceWorkerMsg_NotificationClickEvent(
request_id, notification_database_data.notification_id,
- notification_database_data.notification_data, action_index));
+ notification_database_data.notification_data, action_index, reply));
}
// Dispatches the notification click event on the |service_worker_registration|.
void DoDispatchNotificationClickEvent(
int action_index,
+ const base::NullableString16& reply,
const NotificationDispatchCompleteCallback& dispatch_complete_callback,
const scoped_refptr<PlatformNotificationContext>& notification_context,
const ServiceWorkerRegistration* service_worker_registration,
@@ -229,7 +231,7 @@ void DoDispatchNotificationClickEvent(
base::Bind(
&DispatchNotificationClickEventOnWorker,
make_scoped_refptr(service_worker_registration->active_version()),
- notification_database_data, action_index, status_callback),
+ notification_database_data, action_index, reply, status_callback),
status_callback);
}
@@ -360,10 +362,11 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
const std::string& notification_id,
const GURL& origin,
int action_index,
+ const base::NullableString16& reply,
const NotificationDispatchCompleteCallback& dispatch_complete_callback) {
DispatchNotificationEvent(
browser_context, notification_id, origin,
- base::Bind(&DoDispatchNotificationClickEvent, action_index,
+ base::Bind(&DoDispatchNotificationClickEvent, action_index, reply,
dispatch_complete_callback),
dispatch_complete_callback);
}
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
index 4c7f14d05d3..a0b0399e470 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
@@ -24,6 +24,7 @@ class NotificationEventDispatcherImpl : public NotificationEventDispatcher {
const std::string& notification_id,
const GURL& origin,
int action_index,
+ const base::NullableString16& reply,
const NotificationDispatchCompleteCallback& dispatch_complete_callback)
override;
void DispatchNotificationCloseEvent(
diff --git a/chromium/content/browser/notifications/notification_message_filter.cc b/chromium/content/browser/notifications/notification_message_filter.cc
index 6efe1d2e65e..56064347d26 100644
--- a/chromium/content/browser/notifications/notification_message_filter.cc
+++ b/chromium/content/browser/notifications/notification_message_filter.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "content/browser/bad_message.h"
#include "content/browser/notifications/notification_id_generator.h"
#include "content/browser/notifications/page_notification_delegate.h"
@@ -22,6 +23,7 @@
#include "content/public/browser/platform_notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h"
@@ -51,10 +53,8 @@ PlatformNotificationData SanitizeNotificationData(
// Returns true when |resources| looks ok, false otherwise.
bool ValidateNotificationResources(const NotificationResources& resources) {
- // TODO(johnme): Remove this once https://crbug.com/614456 ships to stable.
if (!resources.image.drawsNothing() &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
+ !base::FeatureList::IsEnabled(features::kNotificationContentImage)) {
return false;
}
if (resources.image.width() > blink::kWebNotificationMaxImageWidthPx ||
diff --git a/chromium/content/browser/payments/OWNERS b/chromium/content/browser/payments/OWNERS
new file mode 100644
index 00000000000..39cc43a4d17
--- /dev/null
+++ b/chromium/content/browser/payments/OWNERS
@@ -0,0 +1,2 @@
+jinho.bang@samsung.com
+rouslan@chromium.org
diff --git a/chromium/content/browser/payments/payment_app_context.cc b/chromium/content/browser/payments/payment_app_context.cc
new file mode 100644
index 00000000000..f56468c9a3f
--- /dev/null
+++ b/chromium/content/browser/payments/payment_app_context.cc
@@ -0,0 +1,68 @@
+// 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/payments/payment_app_context.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
+#include "content/browser/payments/payment_app_manager.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+PaymentAppContext::PaymentAppContext() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+PaymentAppContext::~PaymentAppContext() {
+ DCHECK(services_.empty());
+}
+
+void PaymentAppContext::Init(
+ scoped_refptr<ServiceWorkerContextWrapper> context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+void PaymentAppContext::Shutdown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&PaymentAppContext::ShutdownOnIO, this));
+}
+
+void PaymentAppContext::CreateService(
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PaymentAppContext::CreateServiceOnIOThread, this,
+ base::Passed(&request)));
+}
+
+void PaymentAppContext::ServiceHadConnectionError(PaymentAppManager* service) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::ContainsKey(services_, service));
+
+ services_.erase(service);
+}
+
+void PaymentAppContext::CreateServiceOnIOThread(
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ PaymentAppManager* service = new PaymentAppManager(this, std::move(request));
+ services_[service] = base::WrapUnique(service);
+}
+
+void PaymentAppContext::ShutdownOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ services_.clear();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/payments/payment_app_context.h b/chromium/content/browser/payments/payment_app_context.h
new file mode 100644
index 00000000000..5ffa400fdc0
--- /dev/null
+++ b/chromium/content/browser/payments/payment_app_context.h
@@ -0,0 +1,62 @@
+// 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_PAYMENTS_PAYMENT_APP_CONTEXT_H_
+#define CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_CONTEXT_H_
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/payments/payment_app.mojom.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class PaymentAppManager;
+class ServiceWorkerContextWrapper;
+
+class CONTENT_EXPORT PaymentAppContext
+ : public base::RefCountedThreadSafe<PaymentAppContext> {
+ public:
+ PaymentAppContext();
+
+ // Init and Shutdown are for use on the UI thread when the
+ // StoragePartition is being setup and torn down.
+ void Init(scoped_refptr<ServiceWorkerContextWrapper> context);
+
+ // Shutdown must be called before deleting this. Call on the UI thread.
+ void Shutdown();
+
+ // Create a PaymentAppManager that is owned by this. Call on the UI
+ // thread.
+ void CreateService(
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request);
+
+ // Called by PaymentAppManager objects so that they can
+ // be deleted. Call on the IO thread.
+ void ServiceHadConnectionError(PaymentAppManager* service);
+
+ protected:
+ friend class base::RefCountedThreadSafe<PaymentAppContext>;
+ virtual ~PaymentAppContext();
+
+ private:
+ void CreateServiceOnIOThread(
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request);
+
+ void ShutdownOnIO();
+
+ // The services are owned by this. They're either deleted
+ // during ShutdownOnIO or when the channel is closed via
+ // ServiceHadConnectionError. Only accessed on the IO thread.
+ std::map<PaymentAppManager*, std::unique_ptr<PaymentAppManager>> services_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaymentAppContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_CONTEXT_H_
diff --git a/chromium/content/browser/payments/payment_app_manager.cc b/chromium/content/browser/payments/payment_app_manager.cc
new file mode 100644
index 00000000000..0f0c9ecde16
--- /dev/null
+++ b/chromium/content/browser/payments/payment_app_manager.cc
@@ -0,0 +1,45 @@
+// 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/payments/payment_app_manager.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "content/browser/payments/payment_app_context.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+PaymentAppManager::~PaymentAppManager() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+PaymentAppManager::PaymentAppManager(
+ PaymentAppContext* payment_app_context,
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request)
+ : payment_app_context_(payment_app_context),
+ binding_(this, std::move(request)),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(payment_app_context);
+
+ binding_.set_connection_error_handler(
+ base::Bind(&PaymentAppManager::OnConnectionError,
+ base::Unretained(this)));
+}
+
+void PaymentAppManager::OnConnectionError() {
+ payment_app_context_->ServiceHadConnectionError(this);
+}
+
+void PaymentAppManager::SetManifest(
+ const std::string& scope,
+ payments::mojom::PaymentAppManifestPtr manifest,
+ const SetManifestCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ callback.Run(payments::mojom::PaymentAppManifestError::NOT_IMPLEMENTED);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/payments/payment_app_manager.h b/chromium/content/browser/payments/payment_app_manager.h
new file mode 100644
index 00000000000..7316c217e47
--- /dev/null
+++ b/chromium/content/browser/payments/payment_app_manager.h
@@ -0,0 +1,50 @@
+// 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_PAYMENTS_PAYMENT_APP_MANAGER_H_
+#define CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_MANAGER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/payments/payment_app.mojom.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+
+class PaymentAppContext;
+
+class CONTENT_EXPORT PaymentAppManager
+ : public NON_EXPORTED_BASE(payments::mojom::PaymentAppManager) {
+ public:
+ PaymentAppManager(
+ PaymentAppContext* payment_app_context,
+ mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request);
+
+ ~PaymentAppManager() override;
+
+ private:
+ // payments::mojom::PaymentAppManager methods:
+ void SetManifest(const std::string& scope,
+ payments::mojom::PaymentAppManifestPtr manifest,
+ const SetManifestCallback& callback) override;
+
+ // Called when an error is detected on binding_.
+ void OnConnectionError();
+
+ // payment_app_context_ owns this.
+ PaymentAppContext* payment_app_context_;
+
+ mojo::Binding<payments::mojom::PaymentAppManager> binding_;
+
+ base::WeakPtrFactory<PaymentAppManager> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaymentAppManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_MANAGER_H_
diff --git a/chromium/content/browser/pepper_flash_settings_helper_impl.cc b/chromium/content/browser/pepper_flash_settings_helper_impl.cc
index ab83fb6c07a..70092dd03bf 100644
--- a/chromium/content/browser/pepper_flash_settings_helper_impl.cc
+++ b/chromium/content/browser/pepper_flash_settings_helper_impl.cc
@@ -55,7 +55,7 @@ void PepperFlashSettingsHelperImpl::OnPpapiChannelOpened(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!callback_.is_null());
- if (!channel_handle.name.empty())
+ if (channel_handle.is_mojo_channel_handle())
callback_.Run(true, channel_handle);
else
callback_.Run(false, IPC::ChannelHandle());
diff --git a/chromium/content/browser/permissions/permission_service_context.cc b/chromium/content/browser/permissions/permission_service_context.cc
index a83267a0db7..9292a310d04 100644
--- a/chromium/content/browser/permissions/permission_service_context.cc
+++ b/chromium/content/browser/permissions/permission_service_context.cc
@@ -7,13 +7,53 @@
#include <utility>
#include "content/browser/permissions/permission_service_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/permission_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
+using blink::mojom::PermissionObserverPtr;
+
namespace content {
+class PermissionServiceContext::PermissionSubscription {
+ public:
+ PermissionSubscription(PermissionServiceContext* context,
+ PermissionObserverPtr observer)
+ : context_(context), observer_(std::move(observer)) {
+ observer_.set_connection_error_handler(base::Bind(
+ &PermissionSubscription::OnConnectionError, base::Unretained(this)));
+ }
+
+ ~PermissionSubscription() {
+ DCHECK_NE(id_, 0);
+ BrowserContext* browser_context = context_->GetBrowserContext();
+ DCHECK(browser_context);
+ if (browser_context->GetPermissionManager()) {
+ browser_context->GetPermissionManager()
+ ->UnsubscribePermissionStatusChange(id_);
+ }
+ }
+
+ void OnConnectionError() {
+ DCHECK_NE(id_, 0);
+ context_->ObserverHadConnectionError(id_);
+ }
+
+ void OnPermissionStatusChanged(blink::mojom::PermissionStatus status) {
+ observer_->OnPermissionStatusChange(status);
+ }
+
+ void set_id(int id) { id_ = id; }
+
+ private:
+ PermissionServiceContext* context_;
+ PermissionObserverPtr observer_;
+ int id_ = 0;
+};
+
PermissionServiceContext::PermissionServiceContext(
RenderFrameHost* render_frame_host)
: WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
@@ -33,16 +73,51 @@ PermissionServiceContext::~PermissionServiceContext() {
void PermissionServiceContext::CreateService(
mojo::InterfaceRequest<blink::mojom::PermissionService> request) {
- services_.push_back(new PermissionServiceImpl(this, std::move(request)));
+ services_.push_back(
+ base::MakeUnique<PermissionServiceImpl>(this, std::move(request)));
+}
+
+void PermissionServiceContext::CreateSubscription(
+ PermissionType permission_type,
+ const url::Origin& origin,
+ PermissionObserverPtr observer) {
+ BrowserContext* browser_context = GetBrowserContext();
+ DCHECK(browser_context);
+ if (!browser_context->GetPermissionManager())
+ return;
+
+ auto subscription =
+ base::MakeUnique<PermissionSubscription>(this, std::move(observer));
+ GURL requesting_origin(origin.Serialize());
+ GURL embedding_origin = GetEmbeddingOrigin();
+ int subscription_id =
+ browser_context->GetPermissionManager()->SubscribePermissionStatusChange(
+ permission_type, requesting_origin,
+ // If the embedding_origin is empty, we'll use the |origin| instead.
+ embedding_origin.is_empty() ? requesting_origin : embedding_origin,
+ base::Bind(&PermissionSubscription::OnPermissionStatusChanged,
+ base::Unretained(subscription.get())));
+ subscription->set_id(subscription_id);
+ subscriptions_[subscription_id] = std::move(subscription);
}
void PermissionServiceContext::ServiceHadConnectionError(
PermissionServiceImpl* service) {
- auto it = std::find(services_.begin(), services_.end(), service);
+ auto it = std::find_if(
+ services_.begin(), services_.end(),
+ [service](const std::unique_ptr<PermissionServiceImpl>& this_service) {
+ return service == this_service.get();
+ });
DCHECK(it != services_.end());
services_.erase(it);
}
+void PermissionServiceContext::ObserverHadConnectionError(int subscription_id) {
+ auto it = subscriptions_.find(subscription_id);
+ DCHECK(it != subscriptions_.end());
+ subscriptions_.erase(it);
+}
+
void PermissionServiceContext::RenderFrameHostChanged(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
@@ -65,13 +140,15 @@ void PermissionServiceContext::DidNavigateAnyFrame(
}
void PermissionServiceContext::CancelPendingOperations(
- RenderFrameHost* render_frame_host) const {
+ RenderFrameHost* render_frame_host) {
DCHECK(render_frame_host_);
if (render_frame_host != render_frame_host_)
return;
- for (auto* service : services_)
+ for (const auto& service : services_)
service->CancelPendingOperations();
+
+ subscriptions_.clear();
}
BrowserContext* PermissionServiceContext::GetBrowserContext() const {
diff --git a/chromium/content/browser/permissions/permission_service_context.h b/chromium/content/browser/permissions/permission_service_context.h
index 3db134edd82..11bcc5b6772 100644
--- a/chromium/content/browser/permissions/permission_service_context.h
+++ b/chromium/content/browser/permissions/permission_service_context.h
@@ -7,15 +7,21 @@
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/interface_request.h"
namespace blink {
namespace mojom {
+class PermissionObserver;
class PermissionService;
}
}
+namespace url {
+class Origin;
+}
+
namespace content {
class PermissionServiceImpl;
@@ -36,16 +42,26 @@ class PermissionServiceContext : public WebContentsObserver {
void CreateService(
mojo::InterfaceRequest<blink::mojom::PermissionService> request);
+ void CreateSubscription(
+ PermissionType permission_type,
+ const url::Origin& origin,
+ mojo::InterfacePtr<blink::mojom::PermissionObserver> observer);
+
// Called by a PermissionServiceImpl identified as |service| when it has a
// connection error in order to get unregistered and killed.
void ServiceHadConnectionError(PermissionServiceImpl* service);
+ // Called when the connection to a PermissionObserver has an error.
+ void ObserverHadConnectionError(int subscription_id);
+
BrowserContext* GetBrowserContext() const;
GURL GetEmbeddingOrigin() const;
RenderFrameHost* render_frame_host() const;
private:
+ class PermissionSubscription;
+
// WebContentsObserver
void RenderFrameHostChanged(RenderFrameHost* old_host,
RenderFrameHost* new_host) override;
@@ -54,11 +70,13 @@ class PermissionServiceContext : public WebContentsObserver {
const LoadCommittedDetails& details,
const FrameNavigateParams& params) override;
- void CancelPendingOperations(RenderFrameHost*) const;
+ void CancelPendingOperations(RenderFrameHost*);
RenderFrameHost* render_frame_host_;
RenderProcessHost* render_process_host_;
- ScopedVector<PermissionServiceImpl> services_;
+ std::vector<std::unique_ptr<PermissionServiceImpl>> services_;
+ std::unordered_map<int, std::unique_ptr<PermissionSubscription>>
+ subscriptions_;
DISALLOW_COPY_AND_ASSIGN(PermissionServiceContext);
};
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index 9ad4bb24640..3458e03ef57 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -14,6 +14,7 @@
using blink::mojom::PermissionDescriptorPtr;
using blink::mojom::PermissionName;
+using blink::mojom::PermissionObserverPtr;
using blink::mojom::PermissionStatus;
namespace content {
@@ -78,17 +79,6 @@ PermissionServiceImpl::PendingRequest::~PendingRequest() {
callback.Run(result);
}
-PermissionServiceImpl::PendingSubscription::PendingSubscription(
- PermissionType permission,
- const url::Origin& origin,
- const PermissionStatusCallback& callback)
- : id(-1), permission(permission), origin(origin), callback(callback) {}
-
-PermissionServiceImpl::PendingSubscription::~PendingSubscription() {
- if (!callback.is_null())
- callback.Run(PermissionStatus::ASK);
-}
-
PermissionServiceImpl::PermissionServiceImpl(
PermissionServiceContext* context,
mojo::InterfaceRequest<blink::mojom::PermissionService> request)
@@ -134,7 +124,7 @@ void PermissionServiceImpl::RequestPermission(
base::Bind(&PermissionRequestResponseCallbackWrapper, callback), 1));
int id = browser_context->GetPermissionManager()->RequestPermission(
PermissionDescriptorToPermissionType(permission),
- context_->render_frame_host(), GURL(origin.Serialize()), user_gesture,
+ context_->render_frame_host(), origin.GetURL(), user_gesture,
base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse,
weak_factory_.GetWeakPtr(), pending_request_id));
@@ -184,8 +174,7 @@ void PermissionServiceImpl::RequestPermissions(
int pending_request_id = pending_requests_.Add(
new PendingRequest(callback, permissions.size()));
int id = browser_context->GetPermissionManager()->RequestPermissions(
- types, context_->render_frame_host(), GURL(origin.Serialize()),
- user_gesture,
+ types, context_->render_frame_host(), origin.GetURL(), user_gesture,
base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse,
weak_factory_.GetWeakPtr(), pending_request_id));
@@ -223,17 +212,6 @@ void PermissionServiceImpl::CancelPendingOperations() {
it.GetCurrentValue()->id);
}
pending_requests_.Clear();
-
- // Cancel pending subscriptions.
- for (SubscriptionsMap::Iterator<PendingSubscription>
- it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType(
- it.GetCurrentValue()->permission, it.GetCurrentValue()->origin));
- it.GetCurrentValue()->callback.Reset();
- permission_manager->UnsubscribePermissionStatusChange(
- it.GetCurrentValue()->id);
- }
- pending_subscriptions_.Clear();
}
void PermissionServiceImpl::HasPermission(
@@ -264,43 +242,19 @@ void PermissionServiceImpl::RevokePermission(
callback.Run(GetPermissionStatusFromType(permission_type, origin));
}
-void PermissionServiceImpl::GetNextPermissionChange(
+void PermissionServiceImpl::AddPermissionObserver(
PermissionDescriptorPtr permission,
const url::Origin& origin,
PermissionStatus last_known_status,
- const PermissionStatusCallback& callback) {
+ PermissionObserverPtr observer) {
PermissionStatus current_status = GetPermissionStatus(permission, origin);
if (current_status != last_known_status) {
- callback.Run(current_status);
- return;
+ observer->OnPermissionStatusChange(current_status);
+ last_known_status = current_status;
}
- BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
- if (!browser_context->GetPermissionManager()) {
- callback.Run(current_status);
- return;
- }
-
- PermissionType permission_type =
- PermissionDescriptorToPermissionType(permission);
-
- // We need to pass the id of PendingSubscription in pending_subscriptions_
- // to the callback but SubscribePermissionStatusChange() will also return an
- // id which is different.
- PendingSubscription* subscription =
- new PendingSubscription(permission_type, origin, callback);
- int pending_subscription_id = pending_subscriptions_.Add(subscription);
-
- GURL requesting_origin(origin.Serialize());
- GURL embedding_origin = context_->GetEmbeddingOrigin();
- subscription->id =
- browser_context->GetPermissionManager()->SubscribePermissionStatusChange(
- permission_type, requesting_origin,
- // If the embedding_origin is empty, we,ll use the |origin| instead.
- embedding_origin.is_empty() ? requesting_origin : embedding_origin,
- base::Bind(&PermissionServiceImpl::OnPermissionStatusChanged,
- weak_factory_.GetWeakPtr(), pending_subscription_id));
+ context_->CreateSubscription(PermissionDescriptorToPermissionType(permission),
+ origin, std::move(observer));
}
PermissionStatus PermissionServiceImpl::GetPermissionStatus(
@@ -341,25 +295,4 @@ void PermissionServiceImpl::ResetPermissionStatus(PermissionType type,
embedding_origin.is_empty() ? requesting_origin : embedding_origin);
}
-void PermissionServiceImpl::OnPermissionStatusChanged(
- int pending_subscription_id,
- PermissionStatus status) {
- PendingSubscription* subscription =
- pending_subscriptions_.Lookup(pending_subscription_id);
-
- BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
- if (browser_context->GetPermissionManager()) {
- browser_context->GetPermissionManager()->UnsubscribePermissionStatusChange(
- subscription->id);
- }
-
- PermissionStatusCallback callback = subscription->callback;
-
- subscription->callback.Reset();
- pending_subscriptions_.Remove(pending_subscription_id);
-
- callback.Run(status);
-}
-
} // namespace content
diff --git a/chromium/content/browser/permissions/permission_service_impl.h b/chromium/content/browser/permissions/permission_service_impl.h
index 9321ff4e2e8..dc1f8ed4824 100644
--- a/chromium/content/browser/permissions/permission_service_impl.h
+++ b/chromium/content/browser/permissions/permission_service_impl.h
@@ -27,6 +27,9 @@ enum class PermissionType;
// WebContents for example.
class PermissionServiceImpl : public blink::mojom::PermissionService {
public:
+ PermissionServiceImpl(
+ PermissionServiceContext* context,
+ mojo::InterfaceRequest<blink::mojom::PermissionService> request);
~PermissionServiceImpl() override;
// Clear pending operations currently run by the service. This will be called
@@ -34,13 +37,6 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
// state for example, if the frame changes.
void CancelPendingOperations();
- protected:
- friend PermissionServiceContext;
-
- PermissionServiceImpl(
- PermissionServiceContext* context,
- mojo::InterfaceRequest<blink::mojom::PermissionService> request);
-
private:
using PermissionStatusCallback =
base::Callback<void(blink::mojom::PermissionStatus)>;
@@ -57,20 +53,6 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
};
using RequestsMap = IDMap<PendingRequest, IDMapOwnPointer>;
- struct PendingSubscription {
- PendingSubscription(PermissionType permission,
- const url::Origin& origin,
- const PermissionStatusCallback& callback);
- ~PendingSubscription();
-
- // Subscription ID received from the PermissionManager.
- int id;
- PermissionType permission;
- url::Origin origin;
- PermissionStatusCallback callback;
- };
- using SubscriptionsMap = IDMap<PendingSubscription, IDMapOwnPointer>;
-
// blink::mojom::PermissionService.
void HasPermission(blink::mojom::PermissionDescriptorPtr permission,
const url::Origin& origin,
@@ -87,11 +69,11 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
void RevokePermission(blink::mojom::PermissionDescriptorPtr permission,
const url::Origin& origin,
const PermissionStatusCallback& callback) override;
- void GetNextPermissionChange(
+ void AddPermissionObserver(
blink::mojom::PermissionDescriptorPtr permission,
const url::Origin& origin,
blink::mojom::PermissionStatus last_known_status,
- const PermissionStatusCallback& callback) override;
+ blink::mojom::PermissionObserverPtr observer) override;
void OnConnectionError();
@@ -109,11 +91,7 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
const url::Origin& origin);
void ResetPermissionStatus(PermissionType type, const url::Origin& origin);
- void OnPermissionStatusChanged(int pending_subscription_id,
- blink::mojom::PermissionStatus status);
-
RequestsMap pending_requests_;
- SubscriptionsMap pending_subscriptions_;
// context_ owns |this|.
PermissionServiceContext* context_;
mojo::Binding<blink::mojom::PermissionService> binding_;
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index 6044984e5c5..9ccec641322 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -139,7 +139,7 @@ class PluginDataRemoverImpl::Context
void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
base::ProcessId /* peer_pid */,
int /* child_id */) override {
- if (!channel_handle.name.empty())
+ if (channel_handle.is_mojo_channel_handle())
ConnectToChannel(channel_handle);
// Balancing the AddRef call.
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index 0585c241771..3eca335a09d 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -68,7 +68,7 @@ void PluginService::PurgePluginListCache(BrowserContext* browser_context,
!it.IsAtEnd(); it.Advance()) {
RenderProcessHost* host = it.GetCurrentValue();
if (!browser_context || host->GetBrowserContext() == browser_context)
- host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
+ host->GetRendererInterface()->PurgePluginListCache(reload_pages);
}
}
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index e73e05080be..71bbed2c6e6 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -48,7 +48,6 @@ class SingleThreadTaskRunner;
namespace content {
class BrowserContext;
-class PluginDirWatcherDelegate;
class PluginServiceFilter;
class ResourceContext;
struct PepperPluginInfo;
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.cc b/chromium/content/browser/power_monitor_message_broadcaster.cc
deleted file mode 100644
index e862abbfe74..00000000000
--- a/chromium/content/browser/power_monitor_message_broadcaster.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/power_monitor_message_broadcaster.h"
-
-#include "base/power_monitor/power_monitor.h"
-#include "content/common/power_monitor_messages.h"
-#include "ipc/ipc_sender.h"
-
-namespace content {
-
-PowerMonitorMessageBroadcaster::PowerMonitorMessageBroadcaster(
- IPC::Sender* sender)
- : sender_(sender) {
- base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
- if (power_monitor)
- power_monitor->AddObserver(this);
-}
-
-PowerMonitorMessageBroadcaster::~PowerMonitorMessageBroadcaster() {
- base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
- if (power_monitor)
- power_monitor->RemoveObserver(this);
-}
-
-void PowerMonitorMessageBroadcaster::Init() {
- base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
- // Unit tests does not initialize the PowerMonitor.
- if (power_monitor)
- OnPowerStateChange(power_monitor->IsOnBatteryPower());
-}
-
-void PowerMonitorMessageBroadcaster::OnPowerStateChange(bool on_battery_power) {
- sender_->Send(new PowerMonitorMsg_PowerStateChange(on_battery_power));
-}
-
-void PowerMonitorMessageBroadcaster::OnSuspend() {
- sender_->Send(new PowerMonitorMsg_Suspend());
-}
-
-void PowerMonitorMessageBroadcaster::OnResume() {
- sender_->Send(new PowerMonitorMsg_Resume());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.h b/chromium/content/browser/power_monitor_message_broadcaster.h
deleted file mode 100644
index 4d81e0c4db4..00000000000
--- a/chromium/content/browser/power_monitor_message_broadcaster.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_POWER_MONITOR_MESSAGE_BROADCASTER_H_
-#define CONTENT_BROWSER_POWER_MONITOR_MESSAGE_BROADCASTER_H_
-
-#include "base/macros.h"
-#include "base/power_monitor/power_observer.h"
-#include "content/common/content_export.h"
-
-namespace IPC {
-class Sender;
-}
-
-namespace content {
-
-// A class used to monitor the power state change and communicate it to child
-// processes via IPC.
-class CONTENT_EXPORT PowerMonitorMessageBroadcaster
- : public base::PowerObserver {
- public:
- explicit PowerMonitorMessageBroadcaster(IPC::Sender* sender);
- ~PowerMonitorMessageBroadcaster() override;
-
- // Implement PowerObserver.
- void OnPowerStateChange(bool on_battery_power) override;
- void OnSuspend() override;
- void OnResume() override;
-
- void Init();
-
- private:
- IPC::Sender* sender_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerMonitorMessageBroadcaster);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_POWER_MONITOR_MESSAGE_BROADCASTER_H_
diff --git a/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc b/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc
deleted file mode 100644
index 90add6312d0..00000000000
--- a/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/power_monitor_test_base.h"
-#include "content/browser/power_monitor_message_broadcaster.h"
-#include "content/common/power_monitor_messages.h"
-#include "ipc/ipc_sender.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class PowerMonitorMessageSender : public IPC::Sender {
- public:
- PowerMonitorMessageSender()
- : power_state_changes_(0),
- suspends_(0),
- resumes_(0) {
- }
- ~PowerMonitorMessageSender() override {}
-
- bool Send(IPC::Message* msg) override {
- switch (msg->type()) {
- case PowerMonitorMsg_Suspend::ID:
- suspends_++;
- break;
- case PowerMonitorMsg_Resume::ID:
- resumes_++;
- break;
- case PowerMonitorMsg_PowerStateChange::ID:
- power_state_changes_++;
- break;
- }
- delete msg;
- return true;
- };
-
- // Test status counts.
- int power_state_changes() { return power_state_changes_; }
- int suspends() { return suspends_; }
- int resumes() { return resumes_; }
-
- private:
- int power_state_changes_; // Count of OnPowerStateChange notifications.
- int suspends_; // Count of OnSuspend notifications.
- int resumes_; // Count of OnResume notifications.
-};
-
-class PowerMonitorMessageBroadcasterTest : public testing::Test {
- protected:
- PowerMonitorMessageBroadcasterTest() {
- power_monitor_source_ = new base::PowerMonitorTestSource();
- power_monitor_.reset(new base::PowerMonitor(
- std::unique_ptr<base::PowerMonitorSource>(power_monitor_source_)));
- }
- ~PowerMonitorMessageBroadcasterTest() override {}
-
- base::PowerMonitorTestSource* source() { return power_monitor_source_; }
- base::PowerMonitor* monitor() { return power_monitor_.get(); }
-
- private:
- base::MessageLoop message_loop_;
- base::PowerMonitorTestSource* power_monitor_source_;
- std::unique_ptr<base::PowerMonitor> power_monitor_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerMonitorMessageBroadcasterTest);
-};
-
-TEST_F(PowerMonitorMessageBroadcasterTest, PowerMessageBroadcast) {
- PowerMonitorMessageSender sender;
- PowerMonitorMessageBroadcaster broadcaster(&sender);
-
- // Calling Init should invoke a power state change.
- broadcaster.Init();
- EXPECT_EQ(sender.power_state_changes(), 1);
-
- // Sending resume when not suspended should have no effect.
- source()->GenerateResumeEvent();
- EXPECT_EQ(sender.resumes(), 0);
-
- // Pretend we suspended.
- source()->GenerateSuspendEvent();
- EXPECT_EQ(sender.suspends(), 1);
-
- // Send a second suspend notification. This should be suppressed.
- source()->GenerateSuspendEvent();
- EXPECT_EQ(sender.suspends(), 1);
-
- // Pretend we were awakened.
- source()->GenerateResumeEvent();
- EXPECT_EQ(sender.resumes(), 1);
-
- // Send a duplicate resume notification. This should be suppressed.
- source()->GenerateResumeEvent();
- EXPECT_EQ(sender.resumes(), 1);
-
- // Pretend the device has gone on battery power
- source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(sender.power_state_changes(), 2);
-
- // Repeated indications the device is on battery power should be suppressed.
- source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(sender.power_state_changes(), 2);
-
- // Pretend the device has gone off battery power
- source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(sender.power_state_changes(), 3);
-
- // Repeated indications the device is off battery power should be suppressed.
- source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(sender.power_state_changes(), 3);
-}
-
-} // namespace base
diff --git a/chromium/content/browser/power_usage_monitor_impl.cc b/chromium/content/browser/power_usage_monitor_impl.cc
deleted file mode 100644
index 66911a9e57f..00000000000
--- a/chromium/content/browser/power_usage_monitor_impl.cc
+++ /dev/null
@@ -1,278 +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/power_usage_monitor_impl.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/power_usage_monitor.h"
-#include "content/public/browser/render_process_host.h"
-
-namespace content {
-
-namespace {
-
-// Wait this long after power on before enabling power usage monitoring.
-const int kMinUptimeMinutes = 30;
-
-// Minimum discharge time after which we collect the discharge rate.
-const int kMinDischargeMinutes = 30;
-
-class PowerUsageMonitorSystemInterface
- : public PowerUsageMonitor::SystemInterface {
- public:
- explicit PowerUsageMonitorSystemInterface(PowerUsageMonitor* owner)
- : power_usage_monitor_(owner),
- weak_ptr_factory_(this) {}
- ~PowerUsageMonitorSystemInterface() override {}
-
- void ScheduleHistogramReport(base::TimeDelta delay) override {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &PowerUsageMonitorSystemInterface::ReportBatteryLevelHistogram,
- weak_ptr_factory_.GetWeakPtr(),
- Now(),
- delay),
- delay);
- }
-
- void CancelPendingHistogramReports() override {
- weak_ptr_factory_.InvalidateWeakPtrs();
- }
-
- void RecordDischargePercentPerHour(int percent_per_hour) override {
- UMA_HISTOGRAM_PERCENTAGE("Power.BatteryDischargePercentPerHour",
- percent_per_hour);
- }
-
- base::Time Now() override { return base::Time::Now(); }
-
- protected:
- void ReportBatteryLevelHistogram(base::Time start_time,
- base::TimeDelta discharge_time) {
- // It's conceivable that the code to cancel pending histogram reports on
- // system suspend, will only get called after the system has woken up.
- // To mitigage this, check whether more time has passed than expected and
- // abort histogram recording in this case.
-
- // Delayed tasks are subject to timer coalescing and can fire anywhere from
- // delay -> delay * 1.5) . In most cases, the OS should fire the task
- // at the next wakeup and not as late as it can.
- // A threshold of 2 minutes is used, since that should be large enough to
- // take the slop factor due to coalescing into account.
- base::TimeDelta threshold = discharge_time +
- base::TimeDelta::FromMinutes(2);
- if ((Now() - start_time) > threshold) {
- return;
- }
-
- const std::string histogram_name = base::StringPrintf(
- "Power.BatteryDischarge_%d", discharge_time.InMinutes());
- base::HistogramBase* histogram =
- base::Histogram::FactoryGet(histogram_name,
- 1,
- 100,
- 101,
- base::Histogram::kUmaTargetedHistogramFlag);
- double discharge_amount = power_usage_monitor_->discharge_amount();
- histogram->Add(discharge_amount * 100);
- }
-
- private:
- PowerUsageMonitor* power_usage_monitor_; // Not owned.
-
- // Used to cancel in progress delayed tasks.
- base::WeakPtrFactory<PowerUsageMonitorSystemInterface> weak_ptr_factory_;
-};
-
-} // namespace
-
-void StartPowerUsageMonitor() {
- static base::LazyInstance<PowerUsageMonitor>::Leaky monitor =
- LAZY_INSTANCE_INITIALIZER;
- monitor.Get().Start();
-}
-
-PowerUsageMonitor::PowerUsageMonitor()
- : callback_(base::Bind(&PowerUsageMonitor::OnBatteryStatusUpdate,
- base::Unretained(this))),
- system_interface_(new PowerUsageMonitorSystemInterface(this)),
- started_(false),
- tracking_discharge_(false),
- on_battery_power_(false),
- initial_battery_level_(0),
- current_battery_level_(0) {
-}
-
-PowerUsageMonitor::~PowerUsageMonitor() {
- if (started_)
- base::PowerMonitor::Get()->RemoveObserver(this);
-}
-
-void PowerUsageMonitor::Start() {
- // Power monitoring may be delayed based on uptime, but renderer process
- // lifetime tracking needs to start immediately so processes created before
- // then are accounted for.
- registrar_.Add(this,
- NOTIFICATION_RENDERER_PROCESS_CREATED,
- NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this,
- NOTIFICATION_RENDERER_PROCESS_CLOSED,
- NotificationService::AllBrowserContextsAndSources());
- subscription_ =
- device::BatteryStatusService::GetInstance()->AddCallback(callback_);
-
- // Delay initialization until the system has been up for a while.
- // This is to mitigate the effect of increased power draw during system start.
- base::TimeDelta uptime = base::SysInfo::Uptime();
- base::TimeDelta min_uptime = base::TimeDelta::FromMinutes(kMinUptimeMinutes);
- if (uptime < min_uptime) {
- base::TimeDelta delay = min_uptime - uptime;
- BrowserThread::PostDelayedTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&PowerUsageMonitor::StartInternal, base::Unretained(this)),
- delay);
- } else {
- StartInternal();
- }
-}
-
-void PowerUsageMonitor::StartInternal() {
- DCHECK(!started_);
- started_ = true;
-
- // PowerMonitor is used to get suspend/resume notifications.
- base::PowerMonitor::Get()->AddObserver(this);
-}
-
-void PowerUsageMonitor::DischargeStarted(double battery_level) {
- on_battery_power_ = true;
-
- // If all browser windows are closed, don't report power metrics since
- // Chrome's power draw is likely not significant.
- if (live_renderer_ids_.empty())
- return;
-
- // Cancel any in-progress ReportBatteryLevelHistogram() calls.
- system_interface_->CancelPendingHistogramReports();
-
- tracking_discharge_ = true;
- start_discharge_time_ = system_interface_->Now();
-
- initial_battery_level_ = battery_level;
- current_battery_level_ = battery_level;
-
- const int kBatteryReportingIntervalMinutes[] = {5, 15, 30};
- for (auto reporting_interval : kBatteryReportingIntervalMinutes) {
- base::TimeDelta delay = base::TimeDelta::FromMinutes(reporting_interval);
- system_interface_->ScheduleHistogramReport(delay);
- }
-}
-
-void PowerUsageMonitor::WallPowerConnected(double battery_level) {
- on_battery_power_ = false;
-
- if (tracking_discharge_) {
- DCHECK(!start_discharge_time_.is_null());
- base::TimeDelta discharge_time =
- system_interface_->Now() - start_discharge_time_;
-
- if (discharge_time.InMinutes() > kMinDischargeMinutes) {
- // Record the rate at which the battery discharged over the entire period
- // the system was on battery power.
- double discharge_hours = discharge_time.InSecondsF() / 3600.0;
- int percent_per_hour =
- floor(((discharge_amount() / discharge_hours) * 100.0) + 0.5);
- system_interface_->RecordDischargePercentPerHour(percent_per_hour);
- }
- }
-
- // Cancel any in-progress ReportBatteryLevelHistogram() calls.
- system_interface_->CancelPendingHistogramReports();
-
- initial_battery_level_ = 0;
- current_battery_level_ = 0;
- start_discharge_time_ = base::Time();
- tracking_discharge_ = false;
-}
-
-void PowerUsageMonitor::OnBatteryStatusUpdate(
- const device::BatteryStatus& status) {
- bool now_on_battery_power = (status.charging == 0);
- bool was_on_battery_power = on_battery_power_;
- double battery_level = status.level;
-
- if (now_on_battery_power == was_on_battery_power) {
- if (now_on_battery_power)
- current_battery_level_ = battery_level;
- return;
- } else if (now_on_battery_power) { // Wall power disconnected.
- DischargeStarted(battery_level);
- } else { // Wall power connected.
- WallPowerConnected(battery_level);
- }
-}
-
-void PowerUsageMonitor::OnRenderProcessNotification(int type, int rph_id) {
- size_t previous_num_live_renderers = live_renderer_ids_.size();
-
- if (type == NOTIFICATION_RENDERER_PROCESS_CREATED) {
- live_renderer_ids_.insert(rph_id);
- } else if (type == NOTIFICATION_RENDERER_PROCESS_CLOSED) {
- live_renderer_ids_.erase(rph_id);
- } else {
- NOTREACHED() << "Unexpected notification type: " << type;
- }
-
- if (live_renderer_ids_.empty() && previous_num_live_renderers != 0) {
- // All render processes have died.
- CancelPendingHistogramReporting();
- tracking_discharge_ = false;
- }
-
-}
-
-void PowerUsageMonitor::SetSystemInterfaceForTest(
- std::unique_ptr<SystemInterface> interface) {
- system_interface_ = std::move(interface);
-}
-
-void PowerUsageMonitor::OnPowerStateChange(bool on_battery_power) {
-}
-
-void PowerUsageMonitor::OnResume() {
-}
-
-void PowerUsageMonitor::OnSuspend() {
- CancelPendingHistogramReporting();
-}
-
-void PowerUsageMonitor::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
- OnRenderProcessNotification(type, rph->GetID());
-}
-
-void PowerUsageMonitor::CancelPendingHistogramReporting() {
- // Cancel any in-progress histogram reports and reporting of discharge UMA.
- system_interface_->CancelPendingHistogramReports();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_usage_monitor_impl.h b/chromium/content/browser/power_usage_monitor_impl.h
deleted file mode 100644
index a2c7e96a32f..00000000000
--- a/chromium/content/browser/power_usage_monitor_impl.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_POWER_USAGE_MONITOR_IMPL_H_
-#define CONTENT_BROWSER_POWER_USAGE_MONITOR_IMPL_H_
-
-#include "base/containers/hash_tables.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "device/battery/battery_status_service.h"
-
-namespace content {
-
-// Record statistics on power usage.
-//
-// Two main statics are recorded by this class:
-// * Power.BatteryDischarge_{5,15,30} - delta between battery level when
-// unplugged from wallpower, over the specified period - in minutes.
-// * Power.BatteryDischargeRateWhenUnplugged - the rate of battery discharge
-// from the device being unplugged until it's plugged back in, if said period
-// was longer than 30 minutes.
-//
-// Heuristics:
-// * Data collection starts after system uptime exceeds 30 minutes.
-// * If the machine goes to sleep or all renderers are closed then the current
-// measurement is cancelled.
-class CONTENT_EXPORT PowerUsageMonitor : public base::PowerObserver,
- public NotificationObserver {
- public:
- class SystemInterface {
- public:
- virtual ~SystemInterface() {}
-
- virtual void ScheduleHistogramReport(base::TimeDelta delay) = 0;
- virtual void CancelPendingHistogramReports() = 0;
-
- // Record the battery discharge percent per hour over the time the system
- // is on battery power, legal values [0,100].
- virtual void RecordDischargePercentPerHour(int percent_per_hour) = 0;
-
- // Allow tests to override clock.
- virtual base::Time Now() = 0;
- };
-
- public:
- PowerUsageMonitor();
- ~PowerUsageMonitor() override;
-
- double discharge_amount() const {
- return initial_battery_level_ - current_battery_level_;
- }
-
- // Start monitoring power usage.
- // Note that the actual monitoring will be delayed until 30 minutes after
- // system boot.
- void Start();
-
- void SetSystemInterfaceForTest(std::unique_ptr<SystemInterface> interface);
-
- // Overridden from base::PowerObserver:
- void OnPowerStateChange(bool on_battery_power) override;
- void OnResume() override;
- void OnSuspend() override;
-
- // Overridden from NotificationObserver:
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override;
-
- private:
- friend class PowerUsageMonitorTest;
- FRIEND_TEST_ALL_PREFIXES(PowerUsageMonitorTest, OnBatteryStatusUpdate);
- FRIEND_TEST_ALL_PREFIXES(PowerUsageMonitorTest, OnRenderProcessNotification);
-
- // Start monitoring system power usage.
- // This function may be called after a delay, see Start() for details.
- void StartInternal();
-
- void OnBatteryStatusUpdate(const device::BatteryStatus& status);
- void OnRenderProcessNotification(int type, int rph_id);
-
- void DischargeStarted(double battery_level);
- void WallPowerConnected(double battery_level);
-
- void CancelPendingHistogramReporting();
-
- device::BatteryStatusService::BatteryUpdateCallback callback_;
- std::unique_ptr<device::BatteryStatusService::BatteryUpdateSubscription>
- subscription_;
-
- NotificationRegistrar registrar_;
-
- std::unique_ptr<SystemInterface> system_interface_;
-
- // True if monitoring was started (Start() called).
- bool started_;
-
- // True if collecting metrics for the current discharge cycle e.g. if no
- // renderers are open we don't keep track of discharge.
- bool tracking_discharge_;
-
- // True if the system is running on battery power, false if on wall power.
- bool on_battery_power_;
-
- // Battery level when wall power disconnected. [0.0, 1.0] - 0 if on wall
- // power, 1 means fully charged.
- double initial_battery_level_;
-
- // Current battery level. [0.0, 1.0] - 0 if on wall power, 1 means fully
- // charged.
- double current_battery_level_;
-
- // Timestamp when wall power was disconnected, null Time object otherwise.
- base::Time start_discharge_time_;
-
- // IDs of live renderer processes.
- base::hash_set<int> live_renderer_ids_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PowerUsageMonitor);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_POWER_USAGE_MONITOR_IMPL_H_
diff --git a/chromium/content/browser/power_usage_monitor_impl_unittest.cc b/chromium/content/browser/power_usage_monitor_impl_unittest.cc
deleted file mode 100644
index 1b3446f39bf..00000000000
--- a/chromium/content/browser/power_usage_monitor_impl_unittest.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/power_usage_monitor_impl.h"
-
-#include <utility>
-
-#include "content/public/browser/notification_types.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "device/battery/battery_monitor.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-// Dummy ID to identify a phantom RenderProcessHost in tests.
-const int kDummyRenderProcessHostID = 1;
-
-class SystemInterfaceForTest : public PowerUsageMonitor::SystemInterface {
- public:
- SystemInterfaceForTest()
- : num_pending_histogram_reports_(0),
- discharge_percent_per_hour_(0),
- now_(base::Time::FromInternalValue(1000)) {}
- ~SystemInterfaceForTest() override {}
-
- int num_pending_histogram_reports() const {
- return num_pending_histogram_reports_;
- }
-
- int discharge_percent_per_hour() const {
- return discharge_percent_per_hour_;
- }
-
- void AdvanceClockSeconds(int seconds) {
- now_ += base::TimeDelta::FromSeconds(seconds);
- }
-
- void AdvanceClockMinutes(int minutes) {
- now_ += base::TimeDelta::FromMinutes(minutes);
- }
-
- void ScheduleHistogramReport(base::TimeDelta delay) override {
- num_pending_histogram_reports_++;
- }
-
- void CancelPendingHistogramReports() override {
- num_pending_histogram_reports_ = 0;
- }
-
- void RecordDischargePercentPerHour(int percent_per_hour) override {
- discharge_percent_per_hour_ = percent_per_hour;
- }
-
- base::Time Now() override { return now_; }
-
- private:
- int num_pending_histogram_reports_;
- int discharge_percent_per_hour_;
- base::Time now_;
-};
-
-class PowerUsageMonitorTest : public testing::Test {
- protected:
- void SetUp() override {
- monitor_.reset(new PowerUsageMonitor);
- // PowerUsageMonitor assumes ownership.
- std::unique_ptr<SystemInterfaceForTest> test_interface(
- new SystemInterfaceForTest());
- system_interface_ = test_interface.get();
- monitor_->SetSystemInterfaceForTest(std::move(test_interface));
-
- // Without live renderers, the monitor won't do anything.
- monitor_->OnRenderProcessNotification(NOTIFICATION_RENDERER_PROCESS_CREATED,
- kDummyRenderProcessHostID);
- }
-
- void UpdateBatteryStatus(bool charging, double battery_level) {
- device::BatteryStatus battery_status;
- battery_status.charging = charging;
- battery_status.level = battery_level;
- monitor_->OnBatteryStatusUpdate(battery_status);
- }
-
- void KillTestRenderer() {
- monitor_->OnRenderProcessNotification(
- NOTIFICATION_RENDERER_PROCESS_CLOSED, kDummyRenderProcessHostID);
- }
-
- std::unique_ptr<PowerUsageMonitor> monitor_;
- SystemInterfaceForTest* system_interface_;
- TestBrowserThreadBundle thread_bundle_;
-};
-
-TEST_F(PowerUsageMonitorTest, StartStopQuickly) {
- // Going on battery power.
- UpdateBatteryStatus(false, 1.0);
- int initial_num_histogram_reports =
- system_interface_->num_pending_histogram_reports();
- ASSERT_GT(initial_num_histogram_reports, 0);
-
- // Battery level goes down a bit.
- system_interface_->AdvanceClockSeconds(1);
- UpdateBatteryStatus(false, 0.9);
- ASSERT_EQ(initial_num_histogram_reports,
- system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-
- // Wall power connected.
- system_interface_->AdvanceClockSeconds(30);
- UpdateBatteryStatus(true, 0);
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-}
-
-TEST_F(PowerUsageMonitorTest, DischargePercentReported) {
- // Going on battery power.
- UpdateBatteryStatus(false, 1.0);
- int initial_num_histogram_reports =
- system_interface_->num_pending_histogram_reports();
- ASSERT_GT(initial_num_histogram_reports, 0);
-
- // Battery level goes down a bit.
- system_interface_->AdvanceClockSeconds(30);
- UpdateBatteryStatus(false, 0.9);
- ASSERT_EQ(initial_num_histogram_reports,
- system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-
- // Wall power connected.
- system_interface_->AdvanceClockMinutes(31);
- UpdateBatteryStatus(true, 0);
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
- ASSERT_GT(system_interface_->discharge_percent_per_hour(), 0);
-}
-
-TEST_F(PowerUsageMonitorTest, NoRenderersDisablesMonitoring) {
- KillTestRenderer();
-
- // Going on battery power.
- UpdateBatteryStatus(false, 1.0);
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-
- // Wall power connected.
- system_interface_->AdvanceClockSeconds(30);
- UpdateBatteryStatus(true, 0.5);
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-}
-
-TEST_F(PowerUsageMonitorTest, NoRenderersCancelsInProgressMonitoring) {
- // Going on battery power.
- UpdateBatteryStatus(false, 1.0);
- ASSERT_GT(system_interface_->num_pending_histogram_reports(), 0);
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-
- // All renderers killed.
- KillTestRenderer();
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
-
- // Wall power connected.
- system_interface_->AdvanceClockMinutes(31);
- UpdateBatteryStatus(true, 0);
- ASSERT_EQ(0, system_interface_->num_pending_histogram_reports());
- ASSERT_EQ(0, system_interface_->discharge_percent_per_hour());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 31889089839..83cb49c6087 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -31,7 +31,7 @@
#include "content/public/common/process_type.h"
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "mojo/edk/embedder/embedder.h"
#include "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
@@ -42,6 +42,7 @@
#endif // defined(OS_POSIX)
#if defined(OS_WIN)
+#include "base/win/windows_version.h"
#include "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h"
#include "content/common/sandbox_win.h"
#include "sandbox/win/src/process_mitigations.h"
@@ -60,18 +61,12 @@ ZygoteHandle g_ppapi_zygote;
class PpapiPluginSandboxedProcessLauncherDelegate
: public content::SandboxedProcessLauncherDelegate {
public:
- PpapiPluginSandboxedProcessLauncherDelegate(bool is_broker,
- const PepperPluginInfo& info,
- ChildProcessHost* host)
-#if defined(OS_WIN)
- : info_(info), is_broker_(is_broker) {
-#elif defined(OS_MACOSX) || defined(OS_ANDROID)
- : ipc_fd_(host->TakeClientFileDescriptor()) {
-#elif defined(OS_POSIX)
- : ipc_fd_(host->TakeClientFileDescriptor()), is_broker_(is_broker) {
-#else
- {
+ explicit PpapiPluginSandboxedProcessLauncherDelegate(bool is_broker)
+#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
+ defined(OS_WIN)
+ : is_broker_(is_broker)
#endif
+ {
}
~PpapiPluginSandboxedProcessLauncherDelegate() override {}
@@ -98,16 +93,12 @@ class PpapiPluginSandboxedProcessLauncherDelegate
GetContentClient()->browser();
#if !defined(NACL_WIN64)
- if (IsWin32kRendererLockdownEnabled()) {
- for (const auto& mime_type : info_.mime_types) {
- if (browser_client->IsWin32kLockdownEnabledForMimeType(
- mime_type.mime_type)) {
- result = AddWin32kLockdownPolicy(policy, true);
- if (result != sandbox::SBOX_ALL_OK)
- return false;
- break;
- }
- }
+ // We don't support PPAPI win32k lockdown prior to Windows 10.
+ if (base::win::GetVersion() >= base::win::VERSION_WIN10 &&
+ IsWin32kLockdownEnabled()) {
+ result = AddWin32kLockdownPolicy(policy, true);
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
}
#endif
const base::string16& sid =
@@ -118,8 +109,7 @@ class PpapiPluginSandboxedProcessLauncherDelegate
return true;
}
-#elif defined(OS_POSIX)
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
ZygoteHandle* GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
@@ -129,9 +119,6 @@ class PpapiPluginSandboxedProcessLauncherDelegate
return nullptr;
return GetGenericZygote();
}
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
-
- base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
SandboxType GetSandboxType() override {
@@ -139,12 +126,6 @@ class PpapiPluginSandboxedProcessLauncherDelegate
}
private:
-#if defined(OS_WIN)
- const PepperPluginInfo& info_;
-#endif // OS_WIN
-#if defined(OS_POSIX)
- base::ScopedFD ipc_fd_;
-#endif // OS_POSIX
#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
defined(OS_WIN)
bool is_broker_;
@@ -330,7 +311,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
permissions_ = ppapi::PpapiPermissions::GetForCommandLine(base_permissions);
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_PPAPI_PLUGIN, this, kPluginServiceName));
+ PROCESS_TYPE_PPAPI_PLUGIN, this, mojom::kPluginServiceName));
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions_, info.name,
info.path, profile_data_directory,
@@ -353,7 +334,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
PpapiPluginProcessHost::PpapiPluginProcessHost() : is_broker_(true) {
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_PPAPI_BROKER, this, kPluginServiceName));
+ PROCESS_TYPE_PPAPI_BROKER, this, mojom::kPluginServiceName));
ppapi::PpapiPermissions permissions; // No permissions.
// The plugin name, path and profile data directory shouldn't be needed for
@@ -454,12 +435,8 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
// On posix, never use the zygote for the broker. Also, only use the zygote if
// we are not using a plugin launcher - having a plugin launcher means we need
// to use another process instead of just forking the zygote.
- process_->Launch(
- new PpapiPluginSandboxedProcessLauncherDelegate(is_broker_,
- info,
- process_->GetHost()),
- cmd_line,
- true);
+ process_->Launch(new PpapiPluginSandboxedProcessLauncherDelegate(is_broker_),
+ cmd_line, true);
return true;
}
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index 900d186b1f5..1a23a37ed61 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -181,22 +181,22 @@ void PresentationServiceImpl::SetClient(
}
void PresentationServiceImpl::ListenForScreenAvailability(const GURL& url) {
- DVLOG(2) << "ListenForScreenAvailability " << url;
+ DVLOG(2) << "ListenForScreenAvailability " << url.spec();
if (!delegate_) {
client_->OnScreenAvailabilityUpdated(url, false);
return;
}
- if (screen_availability_listeners_.count(url.spec()))
+ if (screen_availability_listeners_.count(url))
return;
std::unique_ptr<ScreenAvailabilityListenerImpl> listener(
- new ScreenAvailabilityListenerImpl(url.spec(), this));
+ new ScreenAvailabilityListenerImpl(url, this));
if (delegate_->AddScreenAvailabilityListener(
render_process_id_,
render_frame_id_,
listener.get())) {
- screen_availability_listeners_[url.spec()] = std::move(listener);
+ screen_availability_listeners_[url] = std::move(listener);
} else {
DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request.";
}
@@ -208,7 +208,7 @@ void PresentationServiceImpl::StopListeningForScreenAvailability(
if (!delegate_)
return;
- auto listener_it = screen_availability_listeners_.find(url.spec());
+ auto listener_it = screen_availability_listeners_.find(url);
if (listener_it == screen_availability_listeners_.end())
return;
@@ -236,16 +236,10 @@ void PresentationServiceImpl::StartSession(
return;
}
- std::vector<std::string> presentation_urls_for_delegate(
- presentation_urls.size());
- std::transform(presentation_urls.begin(), presentation_urls.end(),
- presentation_urls_for_delegate.begin(),
- [](const GURL& url) { return url.spec(); });
-
start_session_request_id_ = GetNextRequestSessionId();
pending_start_session_cb_.reset(new NewSessionCallbackWrapper(callback));
delegate_->StartSession(
- render_process_id_, render_frame_id_, presentation_urls_for_delegate,
+ render_process_id_, render_frame_id_, presentation_urls,
base::Bind(&PresentationServiceImpl::OnStartSessionSucceeded,
weak_factory_.GetWeakPtr(), start_session_request_id_),
base::Bind(&PresentationServiceImpl::OnStartSessionError,
@@ -265,19 +259,13 @@ void PresentationServiceImpl::JoinSession(
return;
}
- std::vector<std::string> presentation_urls_for_delegate(
- presentation_urls.size());
- std::transform(presentation_urls.begin(), presentation_urls.end(),
- presentation_urls_for_delegate.begin(),
- [](const GURL& url) { return url.spec(); });
-
int request_session_id = RegisterJoinSessionCallback(callback);
if (request_session_id == kInvalidRequestSessionId) {
InvokeNewSessionCallbackWithError(callback);
return;
}
delegate_->JoinSession(
- render_process_id_, render_frame_id_, presentation_urls_for_delegate,
+ render_process_id_, render_frame_id_, presentation_urls,
presentation_id.value_or(std::string()),
base::Bind(&PresentationServiceImpl::OnJoinSessionSucceeded,
weak_factory_.GetWeakPtr(), request_session_id),
@@ -296,13 +284,16 @@ int PresentationServiceImpl::RegisterJoinSessionCallback(
return request_id;
}
-void PresentationServiceImpl::ListenForConnectionStateChange(
+void PresentationServiceImpl::ListenForConnectionStateChangeAndChangeState(
const PresentationSessionInfo& connection) {
if (delegate_) {
delegate_->ListenForConnectionStateChange(
render_process_id_, render_frame_id_, connection,
base::Bind(&PresentationServiceImpl::OnConnectionStateChanged,
weak_factory_.GetWeakPtr(), connection));
+ OnConnectionStateChanged(connection,
+ PresentationConnectionStateChangeInfo(
+ PRESENTATION_CONNECTION_STATE_CONNECTED));
}
}
@@ -316,7 +307,7 @@ void PresentationServiceImpl::OnStartSessionSucceeded(
pending_start_session_cb_->Run(
blink::mojom::PresentationSessionInfo::From(session_info),
blink::mojom::PresentationErrorPtr());
- ListenForConnectionStateChange(session_info);
+ ListenForConnectionStateChangeAndChangeState(session_info);
pending_start_session_cb_.reset();
start_session_request_id_ = kInvalidRequestSessionId;
}
@@ -341,7 +332,7 @@ void PresentationServiceImpl::OnJoinSessionSucceeded(
request_session_id,
blink::mojom::PresentationSessionInfo::From(session_info),
blink::mojom::PresentationErrorPtr())) {
- ListenForConnectionStateChange(session_info);
+ ListenForConnectionStateChangeAndChangeState(session_info);
}
}
@@ -373,18 +364,12 @@ void PresentationServiceImpl::SetDefaultPresentationUrls(
if (!delegate_)
return;
- std::vector<std::string> presentation_urls_for_delegate(
- presentation_urls.size());
- std::transform(presentation_urls.begin(), presentation_urls.end(),
- presentation_urls_for_delegate.begin(),
- [](const GURL& url) { return url.spec(); });
-
- if (default_presentation_urls_ == presentation_urls_for_delegate)
+ if (default_presentation_urls_ == presentation_urls)
return;
- default_presentation_urls_ = presentation_urls_for_delegate;
+ default_presentation_urls_ = presentation_urls;
delegate_->SetDefaultPresentationUrls(
- render_process_id_, render_frame_id_, presentation_urls_for_delegate,
+ render_process_id_, render_frame_id_, presentation_urls,
base::Bind(&PresentationServiceImpl::OnDefaultPresentationStarted,
weak_factory_.GetWeakPtr()));
}
@@ -439,6 +424,9 @@ void PresentationServiceImpl::Terminate(const GURL& presentation_url,
void PresentationServiceImpl::OnConnectionStateChanged(
const PresentationSessionInfo& connection,
const PresentationConnectionStateChangeInfo& info) {
+ DVLOG(2) << "PresentationServiceImpl::OnConnectionStateChanged "
+ << "[presentation_id]: " << connection.presentation_id
+ << " [state]: " << info.state;
DCHECK(client_.get());
if (info.state == PRESENTATION_CONNECTION_STATE_CLOSED) {
client_->OnConnectionClosed(
@@ -574,15 +562,13 @@ void PresentationServiceImpl::OnDefaultPresentationStarted(
DCHECK(client_.get());
client_->OnDefaultSessionStarted(
blink::mojom::PresentationSessionInfo::From(connection));
- ListenForConnectionStateChange(connection);
+ ListenForConnectionStateChangeAndChangeState(connection);
}
-PresentationServiceImpl::ScreenAvailabilityListenerImpl
-::ScreenAvailabilityListenerImpl(
- const std::string& availability_url,
- PresentationServiceImpl* service)
- : availability_url_(availability_url),
- service_(service) {
+PresentationServiceImpl::ScreenAvailabilityListenerImpl::
+ ScreenAvailabilityListenerImpl(const GURL& availability_url,
+ PresentationServiceImpl* service)
+ : availability_url_(availability_url), service_(service) {
DCHECK(service_);
DCHECK(service_->client_.get());
}
@@ -591,20 +577,19 @@ PresentationServiceImpl::ScreenAvailabilityListenerImpl::
~ScreenAvailabilityListenerImpl() {
}
-std::string PresentationServiceImpl::ScreenAvailabilityListenerImpl
- ::GetAvailabilityUrl() const {
+GURL PresentationServiceImpl::ScreenAvailabilityListenerImpl::
+ GetAvailabilityUrl() const {
return availability_url_;
}
void PresentationServiceImpl::ScreenAvailabilityListenerImpl
::OnScreenAvailabilityChanged(bool available) {
- service_->client_->OnScreenAvailabilityUpdated(GURL(availability_url_),
- available);
+ service_->client_->OnScreenAvailabilityUpdated(availability_url_, available);
}
void PresentationServiceImpl::ScreenAvailabilityListenerImpl
::OnScreenAvailabilityNotSupported() {
- service_->client_->OnScreenAvailabilityNotSupported(GURL(availability_url_));
+ service_->client_->OnScreenAvailabilityNotSupported(availability_url_);
}
PresentationServiceImpl::NewSessionCallbackWrapper
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index dea2c88c37d..1a1bb7d5348 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -92,7 +92,7 @@ class CONTENT_EXPORT PresentationServiceImpl
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
MaxPendingJoinSessionRequests);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
- ListenForConnectionStateChange);
+ ListenForConnectionStateChangeAndChangeState);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ListenForConnectionClose);
@@ -110,18 +110,17 @@ class CONTENT_EXPORT PresentationServiceImpl
class CONTENT_EXPORT ScreenAvailabilityListenerImpl
: public PresentationScreenAvailabilityListener {
public:
- ScreenAvailabilityListenerImpl(
- const std::string& availability_url,
- PresentationServiceImpl* service);
+ ScreenAvailabilityListenerImpl(const GURL& availability_url,
+ PresentationServiceImpl* service);
~ScreenAvailabilityListenerImpl() override;
// PresentationScreenAvailabilityListener implementation.
- std::string GetAvailabilityUrl() const override;
+ GURL GetAvailabilityUrl() const override;
void OnScreenAvailabilityChanged(bool available) override;
void OnScreenAvailabilityNotSupported() override;
private:
- const std::string availability_url_;
+ const GURL availability_url_;
PresentationServiceImpl* const service_;
};
@@ -223,8 +222,9 @@ class CONTENT_EXPORT PresentationServiceImpl
void OnSendMessageCallback(bool sent);
// Calls to |delegate_| to start listening for state changes for |connection|.
- // State changes will be returned via |OnConnectionStateChanged|.
- void ListenForConnectionStateChange(
+ // State changes will be returned via |OnConnectionStateChanged|. Change
+ // |connection|'s state to 'connected' after listening.
+ void ListenForConnectionStateChangeAndChangeState(
const PresentationSessionInfo& connection);
// Passed to embedder's implementation of PresentationServiceDelegate for
@@ -256,10 +256,10 @@ class CONTENT_EXPORT PresentationServiceImpl
// availability) to.
blink::mojom::PresentationServiceClientPtr client_;
- std::vector<std::string> default_presentation_urls_;
+ std::vector<GURL> default_presentation_urls_;
using ScreenAvailabilityListenerMap =
- std::map<std::string, std::unique_ptr<ScreenAvailabilityListenerImpl>>;
+ std::map<GURL, std::unique_ptr<ScreenAvailabilityListenerImpl>>;
ScreenAvailabilityListenerMap screen_availability_listeners_;
// For StartSession requests.
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index bb5bcc14afc..9374f4a8f89 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -53,19 +53,11 @@ MATCHER_P(SessionInfoEquals, expected, "") {
const char kPresentationId[] = "presentationId";
const char kPresentationUrl1[] = "http://foo.com/index.html";
const char kPresentationUrl2[] = "http://example.com/index.html";
+const char kPresentationUrl3[] = "http://example.net/index.html";
void DoNothing(blink::mojom::PresentationSessionInfoPtr info,
blink::mojom::PresentationErrorPtr error) {}
-// TODO(crbug.com/632623): Convert downstream APIs to GURL and remove
-// conversions.
-std::vector<GURL> ToGURLs(const std::vector<std::string>& urls) {
- std::vector<GURL> gurls(urls.size());
- std::transform(urls.begin(), urls.end(), gurls.begin(),
- [](const std::string& url) { return GURL(url); });
- return gurls;
-}
-
} // namespace
class MockPresentationServiceDelegate : public PresentationServiceDelegate {
@@ -98,18 +90,18 @@ class MockPresentationServiceDelegate : public PresentationServiceDelegate {
MOCK_METHOD4(SetDefaultPresentationUrls,
void(int render_process_id,
int routing_id,
- const std::vector<std::string>& default_presentation_urls,
+ const std::vector<GURL>& default_presentation_urls,
const PresentationSessionStartedCallback& callback));
MOCK_METHOD5(StartSession,
void(int render_process_id,
int render_frame_id,
- const std::vector<std::string>& presentation_urls,
+ const std::vector<GURL>& presentation_urls,
const PresentationSessionStartedCallback& success_cb,
const PresentationSessionErrorCallback& error_cb));
MOCK_METHOD6(JoinSession,
void(int render_process_id,
int render_frame_id,
- const std::vector<std::string>& presentation_urls,
+ const std::vector<GURL>& presentation_urls,
const std::string& presentation_id,
const PresentationSessionStartedCallback& success_cb,
const PresentationSessionErrorCallback& error_cb));
@@ -209,7 +201,10 @@ class MockPresentationServiceClient
class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
public:
- PresentationServiceImplTest() {}
+ PresentationServiceImplTest()
+ : presentation_url1_(GURL(kPresentationUrl1)),
+ presentation_url2_(GURL(kPresentationUrl2)),
+ presentation_url3_(GURL(kPresentationUrl3)) {}
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
@@ -227,6 +222,9 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
new mojo::Binding<blink::mojom::PresentationServiceClient>(
&mock_client_, mojo::GetProxy(&client_ptr)));
service_impl_->SetClient(std::move(client_ptr));
+
+ presentation_urls_.push_back(presentation_url1_);
+ presentation_urls_.push_back(presentation_url2_);
}
void TearDown() override {
@@ -238,7 +236,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
RenderViewHostImplTestHarness::TearDown();
}
- void ListenForScreenAvailabilityAndWait(const std::string& url,
+ void ListenForScreenAvailabilityAndWait(const GURL& url,
bool delegate_success) {
base::RunLoop run_loop;
// This will call to |service_impl_| via mojo. Process the message
@@ -249,7 +247,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
.WillOnce(DoAll(
InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
Return(delegate_success)));
- service_ptr_->ListenForScreenAvailability(GURL(url));
+ service_ptr_->ListenForScreenAvailability(url);
run_loop.Run();
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
@@ -269,13 +267,13 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
run_loop_quit_closure_.Reset();
}
- void SimulateScreenAvailabilityChangeAndWait(
- const std::string& url, bool available) {
+ void SimulateScreenAvailabilityChangeAndWait(const GURL& url,
+ bool available) {
auto listener_it = service_impl_->screen_availability_listeners_.find(url);
ASSERT_TRUE(listener_it->second);
base::RunLoop run_loop;
- EXPECT_CALL(mock_client_, OnScreenAvailabilityUpdated(GURL(url), available))
+ EXPECT_CALL(mock_client_, OnScreenAvailabilityUpdated(url, available))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
listener_it->second->OnScreenAvailabilityChanged(available);
run_loop.Run();
@@ -288,7 +286,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
void ExpectCleanState() {
EXPECT_TRUE(service_impl_->default_presentation_urls_.empty());
EXPECT_EQ(
- service_impl_->screen_availability_listeners_.find(kPresentationUrl1),
+ service_impl_->screen_availability_listeners_.find(presentation_url1_),
service_impl_->screen_availability_listeners_.end());
EXPECT_FALSE(service_impl_->on_session_messages_callback_.get());
}
@@ -340,7 +338,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
blink::mojom::PresentationSessionInfoPtr session(
blink::mojom::PresentationSessionInfo::New());
- session->url = GURL(kPresentationUrl1);
+ session->url = presentation_url1_;
session->id = kPresentationId;
PresentationSessionMessageCallback message_cb;
@@ -385,18 +383,23 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
client_binding_;
base::Closure run_loop_quit_closure_;
+
+ GURL presentation_url1_;
+ GURL presentation_url2_;
+ GURL presentation_url3_;
+ std::vector<GURL> presentation_urls_;
};
TEST_F(PresentationServiceImplTest, ListenForScreenAvailability) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
- SimulateScreenAvailabilityChangeAndWait(kPresentationUrl1, true);
- SimulateScreenAvailabilityChangeAndWait(kPresentationUrl1, false);
- SimulateScreenAvailabilityChangeAndWait(kPresentationUrl1, true);
+ SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
+ SimulateScreenAvailabilityChangeAndWait(presentation_url1_, false);
+ SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
}
TEST_F(PresentationServiceImplTest, Reset) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
ExpectReset();
service_impl_->Reset();
@@ -404,7 +407,7 @@ TEST_F(PresentationServiceImplTest, Reset) {
}
TEST_F(PresentationServiceImplTest, DidNavigateThisFrame) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
ExpectReset();
service_impl_->DidNavigateAnyFrame(
@@ -415,7 +418,7 @@ TEST_F(PresentationServiceImplTest, DidNavigateThisFrame) {
}
TEST_F(PresentationServiceImplTest, DidNavigateOtherFrame) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
// TODO(imcheng): How to get a different RenderFrameHost?
service_impl_->DidNavigateAnyFrame(
@@ -425,11 +428,11 @@ TEST_F(PresentationServiceImplTest, DidNavigateOtherFrame) {
// Availability is reported and callback is invoked since it was not
// removed.
- SimulateScreenAvailabilityChangeAndWait(kPresentationUrl1, true);
+ SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
}
TEST_F(PresentationServiceImplTest, ThisRenderFrameDeleted) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
ExpectReset();
@@ -440,63 +443,71 @@ TEST_F(PresentationServiceImplTest, ThisRenderFrameDeleted) {
}
TEST_F(PresentationServiceImplTest, OtherRenderFrameDeleted) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, true);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, true);
// TODO(imcheng): How to get a different RenderFrameHost?
service_impl_->RenderFrameDeleted(nullptr);
// Availability is reported and callback should be invoked since listener
// has not been deleted.
- SimulateScreenAvailabilityChangeAndWait(kPresentationUrl1, true);
+ SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
}
TEST_F(PresentationServiceImplTest, DelegateFails) {
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, false);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, false);
ASSERT_EQ(
- service_impl_->screen_availability_listeners_.find(kPresentationUrl1),
+ service_impl_->screen_availability_listeners_.find(presentation_url1_),
service_impl_->screen_availability_listeners_.end());
}
TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrls) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
- EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _, urls, _))
+ EXPECT_CALL(mock_delegate_,
+ SetDefaultPresentationUrls(_, _, presentation_urls_, _))
.Times(1);
- service_impl_->SetDefaultPresentationUrls(ToGURLs(urls));
+ service_impl_->SetDefaultPresentationUrls(presentation_urls_);
// Sets different DPUs.
- std::vector<std::string> more_urls(
- {kPresentationUrl1, kPresentationUrl2, "http://barurl.com/"});
+ std::vector<GURL> more_urls = presentation_urls_;
+ more_urls.push_back(presentation_url3_);
content::PresentationSessionStartedCallback callback;
EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _, more_urls, _))
.WillOnce(SaveArg<3>(&callback));
- service_impl_->SetDefaultPresentationUrls(ToGURLs(more_urls));
+ service_impl_->SetDefaultPresentationUrls(more_urls);
blink::mojom::PresentationSessionInfo session_info;
- session_info.url = GURL(kPresentationUrl2);
+ session_info.url = presentation_url2_;
session_info.id = kPresentationId;
+
base::RunLoop run_loop;
EXPECT_CALL(mock_client_,
OnDefaultSessionStarted(SessionInfoEquals(ByRef(session_info))))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _));
callback.Run(
- content::PresentationSessionInfo(kPresentationUrl2, kPresentationId));
+ content::PresentationSessionInfo(presentation_url2_, kPresentationId));
run_loop.Run();
}
-TEST_F(PresentationServiceImplTest, ListenForConnectionStateChange) {
- content::PresentationSessionInfo connection(kPresentationUrl1,
+TEST_F(PresentationServiceImplTest,
+ ListenForConnectionStateChangeAndChangeState) {
+ content::PresentationSessionInfo connection(presentation_url1_,
kPresentationId);
content::PresentationConnectionStateChangedCallback state_changed_cb;
- EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
- .WillOnce(SaveArg<3>(&state_changed_cb));
- service_impl_->ListenForConnectionStateChange(connection);
-
// Trigger state change. It should be propagated back up to |mock_client_|.
blink::mojom::PresentationSessionInfo presentation_connection;
- presentation_connection.url = GURL(kPresentationUrl1);
+ presentation_connection.url = presentation_url1_;
presentation_connection.id = kPresentationId;
+
+ EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
+ .WillOnce(SaveArg<3>(&state_changed_cb));
+ EXPECT_CALL(mock_client_,
+ OnConnectionStateChanged(
+ SessionInfoEquals(ByRef(presentation_connection)),
+ blink::mojom::PresentationConnectionState::CONNECTED));
+ service_impl_->ListenForConnectionStateChangeAndChangeState(connection);
+
{
base::RunLoop run_loop;
EXPECT_CALL(mock_client_,
@@ -511,17 +522,17 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionStateChange) {
}
TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
- content::PresentationSessionInfo connection(kPresentationUrl1,
+ content::PresentationSessionInfo connection(presentation_url1_,
kPresentationId);
content::PresentationConnectionStateChangedCallback state_changed_cb;
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.WillOnce(SaveArg<3>(&state_changed_cb));
- service_impl_->ListenForConnectionStateChange(connection);
+ service_impl_->ListenForConnectionStateChangeAndChangeState(connection);
// Trigger connection close. It should be propagated back up to
// |mock_client_|.
blink::mojom::PresentationSessionInfo presentation_connection;
- presentation_connection.url = GURL(kPresentationUrl1);
+ presentation_connection.url = presentation_url1_;
presentation_connection.id = kPresentationId;
{
base::RunLoop run_loop;
@@ -542,48 +553,43 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
}
TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrls) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
-
- EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _, urls, _))
+ EXPECT_CALL(mock_delegate_,
+ SetDefaultPresentationUrls(_, _, presentation_urls_, _))
.Times(1);
- service_impl_->SetDefaultPresentationUrls(ToGURLs(urls));
+ service_impl_->SetDefaultPresentationUrls(presentation_urls_);
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
// Same URLs as before; no-ops.
- service_impl_->SetDefaultPresentationUrls(ToGURLs(urls));
+ service_impl_->SetDefaultPresentationUrls(presentation_urls_);
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
}
TEST_F(PresentationServiceImplTest, StartSessionSuccess) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
-
service_ptr_->StartSession(
- ToGURLs(urls),
+ presentation_urls_,
base::Bind(&PresentationServiceImplTest::ExpectNewSessionCallbackSuccess,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationSessionInfo&)> success_cb;
- EXPECT_CALL(mock_delegate_, StartSession(_, _, urls, _, _))
+ EXPECT_CALL(mock_delegate_, StartSession(_, _, presentation_urls_, _, _))
.WillOnce(DoAll(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
SaveArg<3>(&success_cb)));
run_loop.Run();
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- success_cb.Run(PresentationSessionInfo(kPresentationUrl1, kPresentationId));
+ success_cb.Run(PresentationSessionInfo(presentation_url1_, kPresentationId));
SaveQuitClosureAndRunLoop();
}
TEST_F(PresentationServiceImplTest, StartSessionError) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
-
service_ptr_->StartSession(
- ToGURLs(urls),
+ presentation_urls_,
base::Bind(&PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationError&)> error_cb;
- EXPECT_CALL(mock_delegate_, StartSession(_, _, urls, _, _))
+ EXPECT_CALL(mock_delegate_, StartSession(_, _, presentation_urls_, _, _))
.WillOnce(DoAll(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
SaveArg<4>(&error_cb)));
run_loop.Run();
@@ -592,35 +598,33 @@ TEST_F(PresentationServiceImplTest, StartSessionError) {
}
TEST_F(PresentationServiceImplTest, JoinSessionSuccess) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
-
service_ptr_->JoinSession(
- ToGURLs(urls), base::Optional<std::string>(kPresentationId),
+ presentation_urls_, base::Optional<std::string>(kPresentationId),
base::Bind(&PresentationServiceImplTest::ExpectNewSessionCallbackSuccess,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationSessionInfo&)> success_cb;
- EXPECT_CALL(mock_delegate_, JoinSession(_, _, urls, kPresentationId, _, _))
+ EXPECT_CALL(mock_delegate_,
+ JoinSession(_, _, presentation_urls_, kPresentationId, _, _))
.WillOnce(DoAll(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
SaveArg<4>(&success_cb)));
run_loop.Run();
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- success_cb.Run(PresentationSessionInfo(kPresentationUrl1, kPresentationId));
+ success_cb.Run(PresentationSessionInfo(presentation_url1_, kPresentationId));
SaveQuitClosureAndRunLoop();
}
TEST_F(PresentationServiceImplTest, JoinSessionError) {
- std::vector<std::string> urls({kPresentationUrl1, kPresentationUrl2});
-
service_ptr_->JoinSession(
- ToGURLs(urls), base::Optional<std::string>(kPresentationId),
+ presentation_urls_, base::Optional<std::string>(kPresentationId),
base::Bind(&PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationError&)> error_cb;
- EXPECT_CALL(mock_delegate_, JoinSession(_, _, urls, kPresentationId, _, _))
+ EXPECT_CALL(mock_delegate_,
+ JoinSession(_, _, presentation_urls_, kPresentationId, _, _))
.WillOnce(DoAll(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
SaveArg<5>(&error_cb)));
run_loop.Run();
@@ -629,8 +633,7 @@ TEST_F(PresentationServiceImplTest, JoinSessionError) {
}
TEST_F(PresentationServiceImplTest, CloseConnection) {
- GURL url(kPresentationUrl1);
- service_ptr_->CloseConnection(url, kPresentationId);
+ service_ptr_->CloseConnection(presentation_url1_, kPresentationId);
base::RunLoop run_loop;
EXPECT_CALL(mock_delegate_, CloseConnection(_, _, Eq(kPresentationId)))
@@ -639,8 +642,7 @@ TEST_F(PresentationServiceImplTest, CloseConnection) {
}
TEST_F(PresentationServiceImplTest, Terminate) {
- GURL url(kPresentationUrl1);
- service_ptr_->Terminate(url, kPresentationId);
+ service_ptr_->Terminate(presentation_url1_, kPresentationId);
base::RunLoop run_loop;
EXPECT_CALL(mock_delegate_, Terminate(_, _, Eq(kPresentationId)))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
@@ -666,15 +668,14 @@ TEST_F(PresentationServiceImplTest, ListenForSessionMessagesWithEmptyMsg) {
}
TEST_F(PresentationServiceImplTest, StartSessionInProgress) {
- std::vector<std::string> urls({"http://foourl.com/", "http://barurl.com/"});
-
- EXPECT_CALL(mock_delegate_, StartSession(_, _, urls, _, _)).Times(1);
- service_ptr_->StartSession(ToGURLs(urls), base::Bind(&DoNothing));
+ EXPECT_CALL(mock_delegate_, StartSession(_, _, presentation_urls_, _, _))
+ .Times(1);
+ service_ptr_->StartSession(presentation_urls_, base::Bind(&DoNothing));
// This request should fail immediately, since there is already a StartSession
// in progress.
service_ptr_->StartSession(
- ToGURLs(urls),
+ presentation_urls_,
base::Bind(&PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
SaveQuitClosureAndRunLoop();
@@ -685,7 +686,7 @@ TEST_F(PresentationServiceImplTest, SendStringMessage) {
blink::mojom::PresentationSessionInfoPtr session(
blink::mojom::PresentationSessionInfo::New());
- session->url = GURL(kPresentationUrl1);
+ session->url = presentation_url1_;
session->id = kPresentationId;
blink::mojom::SessionMessagePtr message_request(
blink::mojom::SessionMessage::New());
@@ -723,7 +724,7 @@ TEST_F(PresentationServiceImplTest, SendArrayBuffer) {
blink::mojom::PresentationSessionInfoPtr session(
blink::mojom::PresentationSessionInfo::New());
- session->url = GURL(kPresentationUrl1);
+ session->url = presentation_url1_;
session->id = kPresentationId;
blink::mojom::SessionMessagePtr message_request(
blink::mojom::SessionMessage::New());
@@ -767,7 +768,7 @@ TEST_F(PresentationServiceImplTest, SendArrayBufferWithExceedingLimit) {
blink::mojom::PresentationSessionInfoPtr session(
blink::mojom::PresentationSessionInfo::New());
- session->url = GURL(kPresentationUrl1);
+ session->url = presentation_url1_;
session->id = kPresentationId;
blink::mojom::SessionMessagePtr message_request(
blink::mojom::SessionMessage::New());
@@ -798,7 +799,7 @@ TEST_F(PresentationServiceImplTest, SendBlobData) {
blink::mojom::PresentationSessionInfoPtr session(
blink::mojom::PresentationSessionInfo::New());
- session->url = GURL(kPresentationUrl1);
+ session->url = presentation_url1_;
session->id = kPresentationId;
blink::mojom::SessionMessagePtr message_request(
blink::mojom::SessionMessage::New());
@@ -839,12 +840,12 @@ TEST_F(PresentationServiceImplTest, MaxPendingJoinSessionRequests) {
EXPECT_CALL(mock_delegate_, JoinSession(_, _, _, _, _, _))
.Times(num_requests);
for (; i < num_requests; ++i) {
- std::vector<GURL> urls({GURL(base::StringPrintf(presentation_url, i))});
+ std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))};
service_ptr_->JoinSession(urls, base::StringPrintf(presentation_id, i),
base::Bind(&DoNothing));
}
- std::vector<GURL> urls({GURL(base::StringPrintf(presentation_url, i))});
+ std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))};
// Exceeded maximum queue size, should invoke mojo callback with error.
service_ptr_->JoinSession(
urls, base::StringPrintf(presentation_id, i),
@@ -855,11 +856,11 @@ TEST_F(PresentationServiceImplTest, MaxPendingJoinSessionRequests) {
TEST_F(PresentationServiceImplTest, ScreenAvailabilityNotSupported) {
mock_delegate_.set_screen_availability_listening_supported(false);
- GURL url(kPresentationUrl1);
base::RunLoop run_loop;
- EXPECT_CALL(mock_client_, OnScreenAvailabilityNotSupported(url))
+ EXPECT_CALL(mock_client_,
+ OnScreenAvailabilityNotSupported(presentation_url1_))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- ListenForScreenAvailabilityAndWait(kPresentationUrl1, false);
+ ListenForScreenAvailabilityAndWait(presentation_url1_, false);
run_loop.Run();
}
diff --git a/chromium/content/browser/presentation/presentation_type_converters.h b/chromium/content/browser/presentation/presentation_type_converters.h
index 5a3bfb601fc..9285dfae09e 100644
--- a/chromium/content/browser/presentation/presentation_type_converters.h
+++ b/chromium/content/browser/presentation/presentation_type_converters.h
@@ -31,8 +31,7 @@ struct TypeConverter<blink::mojom::PresentationSessionInfoPtr,
const content::PresentationSessionInfo& input) {
blink::mojom::PresentationSessionInfoPtr output(
blink::mojom::PresentationSessionInfo::New());
- // TODO(crbug.com/632623): Convert downstream APIs to use GURL
- output->url = GURL(input.presentation_url);
+ output->url = input.presentation_url;
output->id = input.presentation_id;
return output;
}
@@ -43,8 +42,7 @@ struct TypeConverter<content::PresentationSessionInfo,
blink::mojom::PresentationSessionInfoPtr> {
static content::PresentationSessionInfo Convert(
const blink::mojom::PresentationSessionInfoPtr& input) {
- // TODO(crbug.com/632623): Convert downstream APIs to use GURL
- return content::PresentationSessionInfo(input->url.spec(), input->id);
+ return content::PresentationSessionInfo(input->url, input->id);
}
};
diff --git a/chromium/content/browser/presentation/presentation_type_converters_unittest.cc b/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
index fde2823181e..e3f462363f9 100644
--- a/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
@@ -10,9 +10,9 @@
namespace content {
TEST(PresentationTypeConvertersTest, PresentationSessionInfo) {
- GURL presentation_url("http://fooUrl");
+ GURL presentation_url("http://www.example.com/");
std::string presentation_id("presentationId");
- PresentationSessionInfo session(presentation_url.spec(), presentation_id);
+ PresentationSessionInfo session(presentation_url, presentation_id);
blink::mojom::PresentationSessionInfoPtr session_mojo(
blink::mojom::PresentationSessionInfo::From(session));
EXPECT_FALSE(session_mojo.is_null());
diff --git a/chromium/content/browser/push_messaging/push_messaging_message_filter.cc b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
index 44347dd1508..9820f4f151d 100644
--- a/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -324,8 +324,10 @@ void PushMessagingMessageFilter::DidCheckForExistingRegistration(
SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID);
return;
}
- // TODO(crbug.com/638924): Check that stored sender ID equals
- // data.options.sender_info and throw an exception if they don't match.
+ if (fixed_sender_id != stored_sender_id) {
+ SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH);
+ return;
+ }
auto callback = base::Bind(
&PushMessagingMessageFilter::DidGetEncryptionKeys,
weak_factory_io_to_io_.GetWeakPtr(), data, push_registration_id);
diff --git a/chromium/content/browser/quota/quota_manager_unittest.cc b/chromium/content/browser/quota/quota_manager_unittest.cc
index 0080f611bfe..580d68e0599 100644
--- a/chromium/content/browser/quota/quota_manager_unittest.cc
+++ b/chromium/content/browser/quota/quota_manager_unittest.cc
@@ -1490,8 +1490,7 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
for (iterator itr(origin_info_entries().begin()),
end(origin_info_entries().end());
itr != end; ++itr) {
- if (itr->type == kTemp &&
- GURL("http://foo.com/") == itr->origin) {
+ if (itr->type == kTemp && itr->origin == "http://foo.com/") {
found_origin_in_database = true;
break;
}
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 79ab5a97b7f..3c5cb50da8a 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+cc/switches.h", # For cc command line switches.
"+components/display_compositor",
+ "+components/variations",
"+services/ui/public",
"+third_party/zlib",
@@ -39,9 +40,17 @@ specific_include_rules = {
"render_widget_host_view_aura\.cc": [
"+content/browser/frame_host",
],
+ "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).
"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",
],
}
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 4b8d5bcb2ba..865b29ffa50 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -30,7 +30,6 @@ class BrowserCompositorMacClient {
int compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) = 0;
- virtual void BrowserCompositorMacOnLostCompositorResources() = 0;
virtual void BrowserCompositorMacSendBeginFrame(
const cc::BeginFrameArgs& args) = 0;
};
@@ -110,7 +109,6 @@ class BrowserCompositorMac : public cc::BeginFrameObserver,
int compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) override;
- void DelegatedFrameHostOnLostCompositorResources() override;
void SetBeginFrameSource(cc::BeginFrameSource* source) override;
bool IsAutoResizeEnabled() const override;
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 3ec7423b9e9..4ff716dfe1a 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -86,7 +86,6 @@ class RecyclableCompositorMac : public ui::CompositorObserver {
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override {}
void OnCompositingEnded(ui::Compositor* compositor) override {}
- void OnCompositingAborted(ui::Compositor* compositor) override {}
void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
@@ -445,10 +444,6 @@ void BrowserCompositorMac::DelegatedFrameHostSendReclaimCompositorResources(
compositor_frame_sink_id, is_swap_ack, resources);
}
-void BrowserCompositorMac::DelegatedFrameHostOnLostCompositorResources() {
- client_->BrowserCompositorMacOnLostCompositorResources();
-}
-
void BrowserCompositorMac::SetBeginFrameSource(cc::BeginFrameSource* source) {
if (begin_frame_source_ && needs_begin_frames_)
begin_frame_source_->RemoveObserver(this);
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.h b/chromium/content/browser/renderer_host/clipboard_message_filter.h
index c7b748cabc7..e74d9aeb4ae 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.h
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.h
@@ -22,6 +22,10 @@
class GURL;
+namespace gfx {
+class Size;
+}
+
namespace ui {
class ScopedClipboardWriter;
} // namespace ui
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index e0ab58757cc..91f20de9a03 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -14,7 +14,6 @@
#include "base/android/scoped_java_ref.h"
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/cancelable_callback.h"
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
@@ -49,10 +48,8 @@
#include "cc/trees/layer_tree_settings.h"
#include "components/display_compositor/compositor_overlay_candidate_validator_android.h"
#include "components/display_compositor/gl_helper.h"
-#include "content/browser/android/child_process_launcher_android.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
@@ -64,6 +61,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -214,18 +212,13 @@ void ExternalBeginFrameSource::OnVSync(base::TimeTicks frame_time,
class AndroidOutputSurface : public cc::OutputSurface {
public:
- AndroidOutputSurface(
- scoped_refptr<ContextProviderCommandBuffer> context_provider,
- const base::Callback<void(gpu::Capabilities)>&
- populate_gpu_capabilities_callback)
+ explicit AndroidOutputSurface(
+ scoped_refptr<ContextProviderCommandBuffer> context_provider)
: cc::OutputSurface(std::move(context_provider)),
- populate_gpu_capabilities_callback_(populate_gpu_capabilities_callback),
- swap_buffers_completion_callback_(
- base::Bind(&AndroidOutputSurface::OnSwapBuffersCompleted,
- base::Unretained(this))),
overlay_candidate_validator_(
new display_compositor::
- CompositorOverlayCandidateValidatorAndroid()) {
+ CompositorOverlayCandidateValidatorAndroid()),
+ weak_ptr_factory_(this) {
capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
}
@@ -241,16 +234,13 @@ class AndroidOutputSurface : public cc::OutputSurface {
}
}
- bool BindToClient(cc::OutputSurfaceClient* client) override {
- if (!OutputSurface::BindToClient(client))
- return false;
-
+ void BindToClient(cc::OutputSurfaceClient* client) override {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
- swap_buffers_completion_callback_.callback());
-
- populate_gpu_capabilities_callback_.Run(
- context_provider_->ContextCapabilities());
- return true;
+ base::Bind(&AndroidOutputSurface::OnSwapBuffersCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
}
void EnsureBackbuffer() override {}
@@ -263,6 +253,14 @@ class AndroidOutputSurface : public cc::OutputSurface {
context_provider()->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0);
}
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) override {
+ context_provider()->ContextGL()->ResizeCHROMIUM(
+ size.width(), size.height(), device_scale_factor, has_alpha);
+ }
+
cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
return overlay_candidate_validator_.get();
}
@@ -294,25 +292,24 @@ class AndroidOutputSurface : public cc::OutputSurface {
gfx::SwapResult result,
const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
- client_->DidSwapBuffersComplete();
+ client_->DidReceiveSwapBuffersAck();
}
private:
- base::Callback<void(gpu::Capabilities)> populate_gpu_capabilities_callback_;
- base::CancelableCallback<void(
- const std::vector<ui::LatencyInfo>&,
- gfx::SwapResult,
- const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac)>
- swap_buffers_completion_callback_;
+ cc::OutputSurfaceClient* client_ = nullptr;
std::unique_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator_;
+ base::WeakPtrFactory<AndroidOutputSurface> weak_ptr_factory_;
};
#if defined(ENABLE_VULKAN)
class VulkanOutputSurface : public cc::OutputSurface {
public:
explicit VulkanOutputSurface(
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider)
- : OutputSurface(std::move(vulkan_context_provider)) {}
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : OutputSurface(std::move(vulkan_context_provider)),
+ task_runner_(std::move(task_runner)),
+ weak_ptr_factory_(this) {}
~VulkanOutputSurface() override { Destroy(); }
@@ -337,7 +334,9 @@ class VulkanOutputSurface : public cc::OutputSurface {
void SwapBuffers(cc::CompositorFrame frame) override {
surface_->SwapBuffers();
- PostSwapBuffersComplete();
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&VulkanOutputSurface::SwapBuffersAck,
+ weak_ptr_factory_.GetWeakPtr()));
}
void Destroy() {
@@ -347,14 +346,12 @@ class VulkanOutputSurface : public cc::OutputSurface {
}
}
- void OnSwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result) {
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
- OutputSurface::OnSwapBuffersComplete();
- }
-
private:
+ void SwapBuffersAck() { client_->DidReceiveSwapBuffersAck(); }
+
std::unique_ptr<gpu::VulkanSurface> surface_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ base::WeakPtrFactory<VulkanOutputSurface> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VulkanOutputSurface);
};
@@ -459,7 +456,7 @@ void CompositorImpl::SetSurface(jobject surface) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface);
- GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
+ gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
if (window_) {
// Shut down GL context before unregistering surface.
@@ -467,7 +464,8 @@ void CompositorImpl::SetSurface(jobject surface) {
tracker->RemoveSurface(surface_handle_);
ANativeWindow_release(window_);
window_ = NULL;
- UnregisterViewSurface(surface_handle_);
+
+ tracker->UnregisterViewSurface(surface_handle_);
surface_handle_ = gpu::kNullSurfaceHandle;
}
@@ -485,7 +483,7 @@ void CompositorImpl::SetSurface(jobject surface) {
ANativeWindow_acquire(window);
surface_handle_ = tracker->AddSurfaceForNativeWidget(window);
// Register first, SetVisible() might create a CompositorFrameSink.
- RegisterViewSurface(surface_handle_, j_surface);
+ tracker->RegisterViewSurface(surface_handle_, j_surface);
SetVisible(true);
ANativeWindow_release(window);
}
@@ -507,14 +505,14 @@ void CompositorImpl::CreateLayerTreeHost() {
command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
settings.single_thread_proxy_scheduler = true;
+ animation_host_ = cc::AnimationHost::CreateMainInstance();
+
cc::LayerTreeHostInProcess::InitParams params;
params.client = this;
- params.shared_bitmap_manager = HostSharedBitmapManager::current();
- params.gpu_memory_buffer_manager = BrowserGpuMemoryBufferManager::current();
params.task_graph_runner = g_task_graph_runner.Pointer();
params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
params.settings = &settings;
- params.animation_host = cc::AnimationHost::CreateMainInstance();
+ params.mutator_host = animation_host_.get();
host_ = cc::LayerTreeHostInProcess::CreateSingleThreaded(this, &params);
DCHECK(!host_->IsVisible());
host_->GetLayerTree()->SetRootLayer(root_window_->GetLayer());
@@ -611,15 +609,13 @@ void CompositorImpl::RequestNewCompositorFrameSink() {
}
void CompositorImpl::DidInitializeCompositorFrameSink() {
- num_successive_context_creation_failures_ = 0;
compositor_frame_sink_request_pending_ = false;
}
void CompositorImpl::DidFailToInitializeCompositorFrameSink() {
- LOG(ERROR) << "Failed to init CompositorFrameSink for compositor.";
- LOG_IF(FATAL, ++num_successive_context_creation_failures_ >= 2)
- << "Too many context creation failures. Giving up... ";
- HandlePendingCompositorFrameSinkRequest();
+ // The context is bound/initialized before handing it to the
+ // CompositorFrameSink.
+ NOTREACHED();
}
void CompositorImpl::HandlePendingCompositorFrameSinkRequest() {
@@ -652,8 +648,8 @@ void CompositorImpl::CreateVulkanOutputSurface() {
if (!vulkan_context_provider)
return;
- auto vulkan_surface =
- base::MakeUnique<VulkanOutputSurface>(vulkan_context_provider);
+ auto vulkan_surface = base::MakeUnique<VulkanOutputSurface>(
+ vulkan_context_provider, base::ThreadTaskRunnerHandle::Get());
if (!vulkan_surface->Initialize(window_))
return;
@@ -694,15 +690,20 @@ void CompositorImpl::OnGpuChannelEstablished(
GetCompositorContextAttributes(has_transparent_background_),
false /*support_locking*/, false /*automatic_flushes*/,
std::move(gpu_channel_host));
+ if (!context_provider->BindToCurrentThread()) {
+ LOG(ERROR) << "Failed to init ContextProvider for compositor.";
+ LOG_IF(FATAL, ++num_successive_context_creation_failures_ >= 2)
+ << "Too many context creation failures. Giving up... ";
+ HandlePendingCompositorFrameSinkRequest();
+ break;
+ }
scoped_refptr<ContextProviderCommandBuffer>
context_provider_command_buffer =
static_cast<ContextProviderCommandBuffer*>(
context_provider.get());
auto display_output_surface = base::MakeUnique<AndroidOutputSurface>(
- context_provider_command_buffer,
- base::Bind(&CompositorImpl::PopulateGpuCapabilities,
- base::Unretained(this)));
+ std::move(context_provider_command_buffer));
InitializeDisplay(std::move(display_output_surface), nullptr,
std::move(context_provider));
break;
@@ -716,6 +717,13 @@ void CompositorImpl::InitializeDisplay(
DCHECK(compositor_frame_sink_request_pending_);
pending_swapbuffers_ = 0;
+ num_successive_context_creation_failures_ = 0;
+
+ if (context_provider) {
+ gpu_capabilities_ = context_provider->ContextCapabilities();
+ } else {
+ // TODO(danakj): Populate gpu_capabilities_ for VulkanContextProvider.
+ }
cc::SurfaceManager* manager =
ui::ContextProviderFactory::GetInstance()->GetSurfaceManager();
@@ -729,28 +737,26 @@ void CompositorImpl::InitializeDisplay(
display_.reset(new cc::Display(
HostSharedBitmapManager::current(),
BrowserGpuMemoryBufferManager::current(),
- host_->GetSettings().renderer_settings, std::move(begin_frame_source),
- std::move(display_output_surface), std::move(scheduler),
+ host_->GetSettings().renderer_settings, frame_sink_id_,
+ std::move(begin_frame_source), std::move(display_output_surface),
+ std::move(scheduler),
base::MakeUnique<cc::TextureMailboxDeleter>(task_runner)));
auto compositor_frame_sink =
- vulkan_context_provider ? base::MakeUnique<cc::DirectCompositorFrameSink>(
- frame_sink_id_, manager, display_.get(),
- vulkan_context_provider)
- : base::MakeUnique<cc::DirectCompositorFrameSink>(
- frame_sink_id_, manager, display_.get(),
- context_provider, nullptr);
+ vulkan_context_provider
+ ? base::MakeUnique<cc::DirectCompositorFrameSink>(
+ frame_sink_id_, manager, display_.get(),
+ vulkan_context_provider)
+ : base::MakeUnique<cc::DirectCompositorFrameSink>(
+ frame_sink_id_, manager, display_.get(), context_provider,
+ nullptr, BrowserGpuMemoryBufferManager::current(),
+ HostSharedBitmapManager::current());
display_->SetVisible(true);
display_->Resize(size_);
host_->SetCompositorFrameSink(std::move(compositor_frame_sink));
}
-void CompositorImpl::PopulateGpuCapabilities(
- gpu::Capabilities gpu_capabilities) {
- gpu_capabilities_ = gpu_capabilities;
-}
-
void CompositorImpl::AddObserver(VSyncObserver* observer) {
observer_list_.AddObserver(observer);
}
@@ -774,25 +780,20 @@ bool CompositorImpl::SupportsETC1NonPowerOfTwo() const {
return gpu_capabilities_.texture_format_etc1_npot;
}
-void CompositorImpl::DidPostSwapBuffers() {
- TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
+void CompositorImpl::DidSubmitCompositorFrame() {
+ TRACE_EVENT0("compositor", "CompositorImpl::DidSubmitCompositorFrame");
pending_swapbuffers_++;
}
-void CompositorImpl::DidCompleteSwapBuffers() {
- TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
+void CompositorImpl::DidReceiveCompositorFrameAck() {
+ TRACE_EVENT0("compositor", "CompositorImpl::DidReceiveCompositorFrameAck");
DCHECK_GT(pending_swapbuffers_, 0U);
pending_swapbuffers_--;
client_->OnSwapBuffersCompleted(pending_swapbuffers_);
}
-void CompositorImpl::DidAbortSwapBuffers() {
- TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
- // This really gets called only once from
- // SingleThreadProxy::DidLoseCompositorFrameSinkOnImplThread() when the
- // context was lost.
- if (host_->IsVisible())
- host_->SetNeedsCommit();
+void CompositorImpl::DidLoseCompositorFrameSink() {
+ TRACE_EVENT0("compositor", "CompositorImpl::DidLoseCompositorFrameSink");
client_->OnSwapBuffersCompleted(0);
}
@@ -811,8 +812,8 @@ void CompositorImpl::RequestCopyOfOutputOnRootLayer(
void CompositorImpl::OnVSync(base::TimeTicks frame_time,
base::TimeDelta vsync_period) {
- FOR_EACH_OBSERVER(VSyncObserver, observer_list_,
- OnVSync(frame_time, vsync_period));
+ for (auto& observer : observer_list_)
+ observer.OnVSync(frame_time, vsync_period);
if (needs_begin_frames_)
root_window_->RequestVSyncUpdate();
}
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index a1bf169d4d8..e18b3f58e53 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -29,18 +29,15 @@
#include "ui/android/resources/ui_resource_provider.h"
#include "ui/android/window_android_compositor.h"
-class SkBitmap;
struct ANativeWindow;
namespace cc {
+class AnimationHost;
class Display;
class Layer;
class LayerTreeHost;
class OutputSurface;
-class SurfaceIdAllocator;
-class SurfaceManager;
class VulkanContextProvider;
-class VulkanInProcessContextProvider;
}
namespace content {
@@ -67,8 +64,6 @@ class CONTENT_EXPORT CompositorImpl
static bool IsInitialized();
- void PopulateGpuCapabilities(gpu::Capabilities gpu_capabilities);
-
void AddObserver(VSyncObserver* observer);
void RemoveObserver(VSyncObserver* observer);
void OnNeedsBeginFramesChange(bool needs_begin_frames);
@@ -106,12 +101,12 @@ class CONTENT_EXPORT CompositorImpl
void WillCommit() override {}
void DidCommit() override;
void DidCommitAndDrawFrame() override {}
- void DidCompleteSwapBuffers() override;
+ void DidReceiveCompositorFrameAck() override;
void DidCompletePageScaleAnimation() override {}
// LayerTreeHostSingleThreadClient implementation.
- void DidPostSwapBuffers() override;
- void DidAbortSwapBuffers() override;
+ void DidSubmitCompositorFrame() override;
+ void DidLoseCompositorFrameSink() override;
// WindowAndroidCompositor implementation.
void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) override;
@@ -152,6 +147,7 @@ class CONTENT_EXPORT CompositorImpl
// Destruction order matters here:
base::ObserverList<VSyncObserver, true> observer_list_;
+ std::unique_ptr<cc::AnimationHost> animation_host_;
std::unique_ptr<cc::LayerTreeHost> host_;
ui::ResourceManagerImpl resource_manager_;
diff --git a/chromium/content/browser/renderer_host/context_provider_factory_impl_android.cc b/chromium/content/browser/renderer_host/context_provider_factory_impl_android.cc
index e27a94bbb3a..e3aabd06844 100644
--- a/chromium/content/browser/renderer_host/context_provider_factory_impl_android.cc
+++ b/chromium/content/browser/renderer_host/context_provider_factory_impl_android.cc
@@ -14,7 +14,6 @@
#include "cc/surfaces/surface_manager.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/public/common/content_switches.h"
@@ -139,10 +138,6 @@ cc::FrameSinkId ContextProviderFactoryImpl::AllocateFrameSinkId() {
return cc::FrameSinkId(++next_client_id_, 0 /* sink_id */);
}
-cc::SharedBitmapManager* ContextProviderFactoryImpl::GetSharedBitmapManager() {
- return HostSharedBitmapManager::current();
-}
-
gpu::GpuMemoryBufferManager*
ContextProviderFactoryImpl::GetGpuMemoryBufferManager() {
return BrowserGpuMemoryBufferManager::current();
diff --git a/chromium/content/browser/renderer_host/context_provider_factory_impl_android.h b/chromium/content/browser/renderer_host/context_provider_factory_impl_android.h
index a08c71339d7..88ad611d12c 100644
--- a/chromium/content/browser/renderer_host/context_provider_factory_impl_android.h
+++ b/chromium/content/browser/renderer_host/context_provider_factory_impl_android.h
@@ -17,10 +17,6 @@
#include "gpu/ipc/common/surface_handle.h"
#include "ui/android/context_provider_factory.h"
-namespace cc {
-class VulkanInProcessContextProvider;
-}
-
namespace gpu {
class GpuChannelHost;
class GpuChannelEstablishFactory;
@@ -64,7 +60,6 @@ class CONTENT_EXPORT ContextProviderFactoryImpl
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) override;
cc::SurfaceManager* GetSurfaceManager() override;
cc::FrameSinkId AllocateFrameSinkId() override;
- cc::SharedBitmapManager* GetSharedBitmapManager() override;
gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
private:
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index f10099040f5..7b44703381f 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -279,7 +279,7 @@ void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
TRACE_EVENT0("io", "DatabaseMessageFilter::OnDatabaseGetSpaceAvailable");
quota_manager->GetUsageAndQuota(
- GURL(origin.Serialize()), storage::kStorageTypeTemporary,
+ origin.GetURL(), storage::kStorageTypeTemporary,
base::Bind(&DatabaseMessageFilter::OnDatabaseGetUsageAndQuota, this,
reply_msg));
}
@@ -345,7 +345,7 @@ void DatabaseMessageFilter::OnDatabaseModified(
}
std::string origin_identifier(
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize())));
+ storage::GetIdentifierFromOrigin(origin.GetURL()));
if (!database_connections_.IsDatabaseOpened(origin_identifier,
database_name)) {
bad_message::ReceivedBadMessage(this,
@@ -368,7 +368,7 @@ void DatabaseMessageFilter::OnDatabaseClosed(
}
std::string origin_identifier(
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize())));
+ storage::GetIdentifierFromOrigin(origin.GetURL()));
if (!database_connections_.IsDatabaseOpened(
origin_identifier, database_name)) {
bad_message::ReceivedBadMessage(this,
@@ -391,8 +391,7 @@ void DatabaseMessageFilter::OnHandleSqliteError(
return;
}
db_tracker_->HandleSqliteError(
- storage::GetIdentifierFromOrigin(GURL(origin.Serialize())), database_name,
- error);
+ storage::GetIdentifierFromOrigin(origin.GetURL()), database_name, error);
}
void DatabaseMessageFilter::OnDatabaseSizeChanged(
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index 44ba98b348d..ca5ee37118e 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -82,12 +82,14 @@ DelegatedFrameHost::DelegatedFrameHost(const cc::FrameSinkId& frame_sink_id,
factory->GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_);
factory->GetSurfaceManager()->RegisterSurfaceFactoryClient(frame_sink_id_,
this);
+ surface_factory_ = base::MakeUnique<cc::SurfaceFactory>(
+ frame_sink_id_, factory->GetSurfaceManager(), this);
}
void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
delegated_frame_evictor_->SetVisible(true);
- if (local_frame_id_.is_null() && !released_front_lock_.get()) {
+ if (!local_frame_id_.is_valid() && !released_front_lock_.get()) {
if (compositor_)
released_front_lock_ = compositor_->GetCompositorLock();
}
@@ -216,40 +218,43 @@ cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
const gfx::Point& point,
gfx::Point* transformed_point) {
cc::SurfaceId surface_id(frame_sink_id_, local_frame_id_);
- if (surface_id.is_null())
+ if (!surface_id.is_valid())
return surface_id;
cc::SurfaceHittest hittest(delegate, GetSurfaceManager());
gfx::Transform target_transform;
cc::SurfaceId target_local_frame_id =
hittest.GetTargetSurfaceAtPoint(surface_id, point, &target_transform);
*transformed_point = point;
- if (!target_local_frame_id.is_null())
+ if (target_local_frame_id.is_valid())
target_transform.TransformPoint(transformed_point);
return target_local_frame_id;
}
-gfx::Point DelegatedFrameHost::TransformPointToLocalCoordSpace(
+bool DelegatedFrameHost::TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) {
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) {
cc::SurfaceId surface_id(frame_sink_id_, local_frame_id_);
- if (surface_id.is_null() || original_surface == surface_id)
- return point;
+ if (!surface_id.is_valid())
+ return false;
+ *transformed_point = point;
+ if (original_surface == surface_id)
+ return true;
- gfx::Point transformed_point = point;
cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
- hittest.TransformPointToTargetSurface(original_surface, surface_id,
- &transformed_point);
- return transformed_point;
+ return hittest.TransformPointToTargetSurface(original_surface, surface_id,
+ transformed_point);
}
-gfx::Point DelegatedFrameHost::TransformPointToCoordSpaceForView(
+bool DelegatedFrameHost::TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) {
- if (local_frame_id_.is_null())
- return point;
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) {
+ if (!local_frame_id_.is_valid())
+ return false;
return target_view->TransformPointToLocalCoordSpace(
- point, cc::SurfaceId(frame_sink_id_, local_frame_id_));
+ point, cc::SurfaceId(frame_sink_id_, local_frame_id_), transformed_point);
}
bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
@@ -280,7 +285,7 @@ SkColor DelegatedFrameHost::GetGutterColor() const {
}
void DelegatedFrameHost::UpdateGutters() {
- if (local_frame_id_.is_null()) {
+ if (!local_frame_id_.is_valid()) {
right_gutter_.reset();
bottom_gutter_.reset();
return;
@@ -384,7 +389,7 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
subscriber_texture->target()));
}
- if (surface_factory_.get()) {
+ if (local_frame_id_.is_valid()) {
// To avoid unnecessary composites, go directly to the Surface rather than
// through RequestCopyOfOutput (which goes through the browser
// compositor).
@@ -456,7 +461,7 @@ void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id,
// the DelegatedRendererLayer.
EvictDelegatedFrame();
- surface_factory_.reset();
+ surface_factory_->Reset();
if (!surface_returned_resources_.empty()) {
SendReclaimCompositorResources(last_compositor_frame_sink_id_,
false /* is_swap_ack */);
@@ -474,13 +479,9 @@ void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id,
} else {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
- if (!surface_factory_) {
- surface_factory_ =
- base::MakeUnique<cc::SurfaceFactory>(frame_sink_id_, manager, this);
- }
- if (local_frame_id_.is_null() || frame_size != current_surface_size_ ||
+ if (!local_frame_id_.is_valid() || frame_size != current_surface_size_ ||
frame_size_in_dip != current_frame_size_in_dip_) {
- if (!local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
surface_factory_->Destroy(local_frame_id_);
local_frame_id_ = id_allocator_->GenerateId();
surface_factory_->Create(local_frame_id_);
@@ -535,7 +536,7 @@ void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id,
} else {
can_lock_compositor_ = NO_PENDING_COMMIT;
}
- if (!local_frame_id_.is_null()) {
+ if (local_frame_id_.is_valid()) {
delegated_frame_evictor_->SwappedFrame(
client_->DelegatedFrameHostIsVisible());
}
@@ -543,7 +544,7 @@ void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id,
}
void DelegatedFrameHost::ClearDelegatedFrame() {
- if (!local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
EvictDelegatedFrame();
}
@@ -594,7 +595,7 @@ void DelegatedFrameHost::SetBeginFrameSource(
void DelegatedFrameHost::EvictDelegatedFrame() {
client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
- if (!local_frame_id_.is_null()) {
+ if (local_frame_id_.is_valid()) {
surface_factory_->Destroy(local_frame_id_);
local_frame_id_ = cc::LocalFrameId();
}
@@ -791,8 +792,6 @@ void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor,
void DelegatedFrameHost::OnCompositingEnded(ui::Compositor* compositor) {}
-void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {}
-
void DelegatedFrameHost::OnCompositingLockStateChanged(
ui::Compositor* compositor) {
// A compositor lock that is part of a resize lock timed out. We
@@ -818,12 +817,10 @@ void DelegatedFrameHost::OnUpdateVSyncParameters(base::TimeTicks timebase,
// DelegatedFrameHost, ImageTransportFactoryObserver implementation:
void DelegatedFrameHost::OnLostResources() {
- if (!local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
EvictDelegatedFrame();
idle_frame_subscriber_textures_.clear();
yuv_readback_pipeline_.reset();
-
- client_->DelegatedFrameHostOnLostCompositorResources();
}
////////////////////////////////////////////////////////////////////////////////
@@ -834,7 +831,7 @@ DelegatedFrameHost::~DelegatedFrameHost() {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->GetContextFactory()->RemoveObserver(this);
- if (!local_frame_id_.is_null())
+ if (local_frame_id_.is_valid())
surface_factory_->Destroy(local_frame_id_);
factory->GetSurfaceManager()->UnregisterSurfaceFactoryClient(frame_sink_id_);
factory->GetSurfaceManager()->InvalidateFrameSinkId(frame_sink_id_);
@@ -874,7 +871,7 @@ void DelegatedFrameHost::ResetCompositor() {
}
void DelegatedFrameHost::LockResources() {
- DCHECK(!local_frame_id_.is_null());
+ DCHECK(local_frame_id_.is_valid());
delegated_frame_evictor_->LockFrame();
}
@@ -889,7 +886,7 @@ void DelegatedFrameHost::RequestCopyOfOutput(
}
void DelegatedFrameHost::UnlockResources() {
- DCHECK(!local_frame_id_.is_null());
+ DCHECK(local_frame_id_.is_valid());
delegated_frame_evictor_->UnlockFrame();
}
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index b1decdfa16d..a24a821641f 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -46,7 +46,6 @@ namespace content {
class DelegatedFrameHost;
class RenderWidgetHostViewFrameSubscriber;
-class RenderWidgetHostImpl;
class ResizeLock;
// The DelegatedFrameHostClient is the interface from the DelegatedFrameHost,
@@ -71,7 +70,6 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
int compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) = 0;
- virtual void DelegatedFrameHostOnLostCompositorResources() = 0;
virtual void SetBeginFrameSource(cc::BeginFrameSource* source) = 0;
virtual bool IsAutoResizeEnabled() const = 0;
@@ -98,7 +96,6 @@ class CONTENT_EXPORT DelegatedFrameHost
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override;
- void OnCompositingAborted(ui::Compositor* compositor) override;
void OnCompositingLockStateChanged(ui::Compositor* compositor) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
@@ -156,19 +153,20 @@ class CONTENT_EXPORT DelegatedFrameHost
// Given the SurfaceID of a Surface that is contained within this class'
// Surface, find the relative transform between the Surfaces and apply it
- // to a point. If a Surface has not yet been created this returns the
- // same point with no transform applied.
- gfx::Point TransformPointToLocalCoordSpace(
- const gfx::Point& point,
- const cc::SurfaceId& original_surface);
+ // to a point. Returns false if a Surface has not yet been created or if
+ // |original_surface| is not embedded within our current Surface.
+ bool TransformPointToLocalCoordSpace(const gfx::Point& point,
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point);
// Given a RenderWidgetHostViewBase that renders to a Surface that is
// contained within this class' Surface, find the relative transform between
- // the Surfaces and apply it to a point. If a Surface has not yet been
- // created this returns the same point with no transform applied.
- gfx::Point TransformPointToCoordSpaceForView(
- const gfx::Point& point,
- RenderWidgetHostViewBase* target_view);
+ // the Surfaces and apply it to a point. Returns false if a Surface has not
+ // yet been created or if |target_view| is not a descendant RWHV from our
+ // client.
+ bool TransformPointToCoordSpaceForView(const gfx::Point& point,
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point);
// Exposed for tests.
cc::SurfaceId SurfaceIdForTesting() const {
diff --git a/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h b/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
index 4804d975d92..5569182aedd 100644
--- a/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
+++ b/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
@@ -11,16 +11,8 @@
#include "content/public/browser/browser_message_filter.h"
#include "device/gamepad/gamepad_consumer.h"
-namespace device {
-
-class GamepadService;
-
-}
-
namespace content {
-class RenderProcessHost;
-
class GamepadBrowserMessageFilter :
public BrowserMessageFilter,
public device::GamepadConsumer {
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index 8107f74abb5..095c109400a 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -29,9 +29,9 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "jni/ImeAdapter_jni.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebTextInputType.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebTextInputType.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
@@ -285,7 +285,7 @@ void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*,
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
if (rfh)
- rfh->ExtendSelectionAndDelete(before, after);
+ rfh->DeleteSurroundingText(before, after);
}
bool ImeAdapterAndroid::RequestTextInputStateUpdate(
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.h b/chromium/content/browser/renderer_host/ime_adapter_android.h
index 1c4c45915ef..e2f6d6a82e9 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.h
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.h
@@ -18,7 +18,6 @@ class RenderFrameHost;
class RenderWidgetHostImpl;
class RenderWidgetHostViewAndroid;
class WebContents;
-struct NativeWebKeyboardEvent;
// This class is in charge of dispatching key events from the java side
// and forward to renderer along with input method results via
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 aa8d7a153a9..3f1e240d3f2 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -18,12 +18,11 @@
#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/transform.h"
namespace content {
class GestureEventQueueTest;
-class InputRouter;
class MockRenderWidgetHost;
// Interface with which the GestureEventQueue can forward gesture events, and
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 adb62bc1e7f..eb09b8e8817 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
@@ -21,7 +21,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
using base::TimeDelta;
using blink::WebGestureDevice;
diff --git a/chromium/content/browser/renderer_host/input/input_ack_handler.h b/chromium/content/browser/renderer_host/input/input_ack_handler.h
index 22686816004..63fa500333c 100644
--- a/chromium/content/browser/renderer_host/input/input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/input_ack_handler.h
@@ -8,7 +8,7 @@
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/native_web_keyboard_event.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index ee940d5f775..60e77c9d316 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -9,12 +9,10 @@
#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "ipc/ipc_listener.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
-class InputRouterClient;
-
// The InputRouter allows the embedder to customize how input events are
// sent to the renderer, and how responses are dispatched to the browser.
// While the router should respect the relative order in which events are
diff --git a/chromium/content/browser/renderer_host/input/input_router_client.h b/chromium/content/browser/renderer_host/input/input_router_client.h
index fab52aed88a..02215337382 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -7,9 +7,10 @@
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_source.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/native_web_keyboard_event.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace ui {
class LatencyInfo;
@@ -33,10 +34,10 @@ class CONTENT_EXPORT InputRouterClient {
const ui::LatencyInfo& latency_info) = 0;
// Called each time a WebInputEvent IPC is sent.
- virtual void IncrementInFlightEventCount() = 0;
+ virtual void IncrementInFlightEventCount(blink::WebInputEvent::Type type) = 0;
// Called each time a WebInputEvent ACK IPC is received.
- virtual void DecrementInFlightEventCount() = 0;
+ virtual void DecrementInFlightEventCount(InputEventAckSource ack_source) = 0;
// Called when the renderer notifies that it has touch event handlers.
virtual void OnHasTouchEventHandlers(bool has_handlers) = 0;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
index 3e6bf114db6..85d26abe076 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -59,6 +59,8 @@ const char* GetEventAckName(InputEventAckState ack_result) {
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 "";
@@ -98,7 +100,6 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
}
InputRouterImpl::~InputRouterImpl() {
- STLDeleteElements(&pending_select_messages_);
}
bool InputRouterImpl::SendInput(std::unique_ptr<IPC::Message> message) {
@@ -319,11 +320,10 @@ bool InputRouterImpl::SendSelectMessage(std::unique_ptr<IPC::Message> message) {
if (select_message_pending_) {
if (!pending_select_messages_.empty() &&
pending_select_messages_.back()->type() == message->type()) {
- delete pending_select_messages_.back();
pending_select_messages_.pop_back();
}
- pending_select_messages_.push_back(message.release());
+ pending_select_messages_.push_back(std::move(message));
return true;
}
@@ -433,14 +433,14 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
// renderer. Consequently, such event types should not affect event time
// or in-flight event count metrics.
if (dispatch_type == InputEventDispatchType::DISPATCH_TYPE_BLOCKING)
- client_->IncrementInFlightEventCount();
+ client_->IncrementInFlightEventCount(input_event.type);
return true;
}
return false;
}
void InputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
- client_->DecrementInFlightEventCount();
+ client_->DecrementInFlightEventCount(ack.source);
if (ack.overscroll) {
DCHECK(ack.type == WebInputEvent::MouseWheel ||
@@ -466,7 +466,7 @@ void InputRouterImpl::OnSelectMessageAck() {
select_message_pending_ = false;
if (!pending_select_messages_.empty()) {
std::unique_ptr<IPC::Message> next_message =
- base::WrapUnique(pending_select_messages_.front());
+ std::move(pending_select_messages_.front());
pending_select_messages_.pop_front();
SendSelectMessage(std::move(next_message));
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index b2b2a06b3c5..338bc1e0616 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -35,7 +35,6 @@ namespace content {
class InputAckHandler;
class InputRouterClient;
-class OverscrollController;
struct InputEventAck;
// A default implementation for browser input event routing.
@@ -209,9 +208,9 @@ class CONTENT_EXPORT InputRouterImpl
// or MoveRangeSelectionExtent_ACK.
bool select_message_pending_;
- // Queue of pending select messages to send after receving the next select
+ // Queue of pending select messages to send after receiving the next select
// message ack.
- std::deque<IPC::Message*> pending_select_messages_;
+ std::deque<std::unique_ptr<IPC::Message>> pending_select_messages_;
// True while waiting for MoveCaret_ACK.
bool move_caret_pending_;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
index 01f1b4e795a..4511d65b23b 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
@@ -83,8 +83,9 @@ class NullInputRouterClient : public InputRouterClient {
const ui::LatencyInfo& latency_info) override {
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
- void IncrementInFlightEventCount() override {}
- void DecrementInFlightEventCount() override {}
+ void IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) override {}
+ void DecrementInFlightEventCount(InputEventAckSource ack_source) override {}
void OnHasTouchEventHandlers(bool has_handlers) override {}
void DidFlush() override {}
void DidOverscroll(const ui::DidOverscrollParams& params) override {}
@@ -246,7 +247,8 @@ class InputRouterImplPerfTest : public testing::Test {
InputEventAckState ack_result) {
if (!ui::WebInputEventTraits::ShouldBlockEventStream(event))
return;
- InputEventAck ack(event.type, ack_result);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, event.type,
+ ack_result);
InputHostMsg_HandleInputEvent_ACK response(0, ack);
input_router_->OnMessageReceived(response);
}
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 4b0b2bc7205..564cdcff31f 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -286,7 +286,7 @@ class InputRouterImplTest : public testing::Test {
void SendInputEventACK(blink::WebInputEvent::Type type,
InputEventAckState ack_result) {
DCHECK(!WebInputEvent::isTouchEventType(type));
- InputEventAck ack(type, ack_result);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result);
input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
}
@@ -294,7 +294,8 @@ class InputRouterImplTest : public testing::Test {
InputEventAckState ack_result,
uint32_t touch_event_id) {
DCHECK(WebInputEvent::isTouchEventType(type));
- InputEventAck ack(type, ack_result, touch_event_id);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result,
+ touch_event_id);
input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
}
@@ -1815,7 +1816,8 @@ TEST_F(InputRouterImplTest, OverscrollDispatch) {
wheel_overscroll.current_fling_velocity = gfx::Vector2dF(1, 0);
SimulateWheelEvent(0, 0, 3, 0, 0, false);
- InputEventAck ack(WebInputEvent::MouseWheel,
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
+ WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ack.overscroll.reset(new DidOverscrollParams(wheel_overscroll));
input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
diff --git a/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc b/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
index 947228d53cc..1e703be798d 100644
--- a/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
@@ -25,7 +25,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/event_switches.h"
#include "ui/events/latency_info.h"
@@ -123,6 +123,9 @@ class MainThreadEventQueueBrowserTest : public ContentBrowserTest {
// Runs until we get the InputMsgAck callback.
EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, input_msg_watcher->WaitForAck());
+ EXPECT_EQ(InputEventAckSource::MAIN_THREAD,
+ static_cast<InputEventAckSource>(
+ input_msg_watcher->last_event_ack_source()));
int mouse_move_count = 0;
while (mouse_move_count <= 0)
@@ -160,6 +163,9 @@ class MainThreadEventQueueBrowserTest : public ContentBrowserTest {
// Runs until we get the InputMsgAck callback.
EXPECT_EQ(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING,
input_msg_watcher->WaitForAck());
+ EXPECT_EQ(InputEventAckSource::COMPOSITOR_THREAD,
+ static_cast<InputEventAckSource>(
+ input_msg_watcher->last_event_ack_source()));
int touch_move_count = 0;
while (touch_move_count <= 0)
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
index 0adb140f301..2a3cde07000 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -37,11 +37,13 @@ InputEventAckState MockInputRouterClient::FilterInputEvent(
return filter_state_;
}
-void MockInputRouterClient::IncrementInFlightEventCount() {
+void MockInputRouterClient::IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) {
++in_flight_event_count_;
}
-void MockInputRouterClient::DecrementInFlightEventCount() {
+void MockInputRouterClient::DecrementInFlightEventCount(
+ InputEventAckSource ack_source) {
--in_flight_event_count_;
}
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index beeb084b835..463d7f694f4 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -26,8 +26,9 @@ class MockInputRouterClient : public InputRouterClient {
InputEventAckState FilterInputEvent(
const blink::WebInputEvent& input_event,
const ui::LatencyInfo& latency_info) override;
- void IncrementInFlightEventCount() override;
- void DecrementInFlightEventCount() override;
+ void IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) override;
+ void DecrementInFlightEventCount(InputEventAckSource ack_source) override;
void OnHasTouchEventHandlers(bool has_handlers) override;
void DidFlush() override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.h b/chromium/content/browser/renderer_host/input/motion_event_web.h
index 320e31b081b..971e1a31c96 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.h
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/gesture_detection/motion_event.h"
namespace content {
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 d49a120d22e..72d9e95ca70 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
@@ -4,8 +4,8 @@
#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "ui/events/blink/web_input_event_traits.h"
@@ -46,8 +46,6 @@ MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
}
MouseWheelEventQueue::~MouseWheelEventQueue() {
- if (!wheel_queue_.empty())
- base::STLDeleteElements(&wheel_queue_);
}
void MouseWheelEventQueue::QueueEvent(
@@ -55,7 +53,7 @@ void MouseWheelEventQueue::QueueEvent(
TRACE_EVENT0("input", "MouseWheelEventQueue::QueueEvent");
if (event_sent_for_gesture_ack_ && !wheel_queue_.empty()) {
- QueuedWebMouseWheelEvent* last_event = wheel_queue_.back();
+ QueuedWebMouseWheelEvent* last_event = wheel_queue_.back().get();
if (last_event->CanCoalesceWith(event)) {
last_event->CoalesceWith(event);
TRACE_EVENT_INSTANT2("input", "MouseWheelEventQueue::CoalescedWheelEvent",
@@ -66,7 +64,7 @@ void MouseWheelEventQueue::QueueEvent(
}
}
- wheel_queue_.push_back(new QueuedWebMouseWheelEvent(event));
+ wheel_queue_.push_back(base::MakeUnique<QueuedWebMouseWheelEvent>(event));
TryForwardNextEventToRenderer();
LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", wheel_queue_.size());
}
@@ -191,7 +189,7 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
}
if (needs_update) {
- ui::LatencyInfo latency = ui::LatencyInfo();
+ ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL);
latency.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
0);
@@ -250,7 +248,7 @@ void MouseWheelEventQueue::TryForwardNextEventToRenderer() {
if (wheel_queue_.empty() || event_sent_for_gesture_ack_)
return;
- event_sent_for_gesture_ack_.reset(wheel_queue_.front());
+ event_sent_for_gesture_ack_ = std::move(wheel_queue_.front());
wheel_queue_.pop_front();
client_->SendMouseWheelEventImmediately(*event_sent_for_gesture_ack_);
@@ -278,7 +276,8 @@ void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
if (scroll_end_timer_.IsRunning())
scroll_end_timer_.Reset();
}
- client_->ForwardGestureEventWithLatencyInfo(scroll_end, ui::LatencyInfo());
+ client_->ForwardGestureEventWithLatencyInfo(
+ scroll_end, ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
void MouseWheelEventQueue::SendScrollBegin(
@@ -301,7 +300,8 @@ void MouseWheelEventQueue::SendScrollBegin(
needs_scroll_begin_ = false;
needs_scroll_end_ = true;
- client_->ForwardGestureEventWithLatencyInfo(scroll_begin, ui::LatencyInfo());
+ client_->ForwardGestureEventWithLatencyInfo(
+ scroll_begin, ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
index 6b1387c7183..1f465b5051c 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
@@ -6,13 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
#include <deque>
+#include <memory>
#include "base/time/time.h"
#include "base/timer/timer.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 "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
@@ -86,8 +87,7 @@ class CONTENT_EXPORT MouseWheelEventQueue {
MouseWheelEventQueueClient* client_;
base::OneShotTimer scroll_end_timer_;
- typedef std::deque<QueuedWebMouseWheelEvent*> WheelEventQueue;
- WheelEventQueue wheel_queue_;
+ std::deque<std::unique_ptr<QueuedWebMouseWheelEvent>> wheel_queue_;
std::unique_ptr<QueuedWebMouseWheelEvent> event_sent_for_gesture_ack_;
// True if a non-synthetic GSB needs to be sent before a GSU is sent.
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
index fc6995e8fe3..7bc5d637b6f 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
@@ -17,7 +17,7 @@
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
using blink::WebGestureEvent;
using blink::WebInputEvent;
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h b/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
index ffed162c97d..7692447135e 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_RAILS_FILTER_MAC_H_
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc b/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc
index 858a53a341e..d7bd5633ea8 100644
--- a/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc
@@ -25,7 +25,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/event_switches.h"
#include "ui/events/latency_info.h"
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 38079dd70be..a8d3ac23f52 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
@@ -92,6 +92,33 @@ void UpdateLatencyCoordinates(const WebInputEvent& event,
(end.event_time - start.event_time).InMicroseconds(), \
1, 50000, 50)
+// Check valid timing for start and end latency components.
+#define CONFIRM_VALID_TIMING(start, end) \
+ DCHECK(!start.first_event_time.is_null()); \
+ DCHECK(!end.last_event_time.is_null()); \
+ DCHECK_GE(end.last_event_time, start.first_event_time);
+
+// Touch/wheel to scroll latency that is mostly under 1 second.
+#define UMA_HISTOGRAM_TOUCH_WHEEL_TO_SCROLL_LATENCY(name, start, end) \
+ CONFIRM_VALID_TIMING(start, end) \
+ base::Histogram::FactoryGet(name, 1, 1000000, 100, \
+ base::HistogramBase::kUmaTargetedHistogramFlag) \
+ ->Add((end.last_event_time - start.first_event_time).InMicroseconds());
+
+// Long touch/wheel scroll latency component that is mostly under 200ms.
+#define UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(name, start, end) \
+ CONFIRM_VALID_TIMING(start, end) \
+ base::Histogram::FactoryGet(name, 1000, 200000, 50, \
+ base::HistogramBase::kUmaTargetedHistogramFlag) \
+ ->Add((end.last_event_time - start.first_event_time).InMicroseconds());
+
+// Short touch/wheel scroll latency component that is mostly under 50ms.
+#define UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(name, start, end) \
+ CONFIRM_VALID_TIMING(start, end) \
+ base::Histogram::FactoryGet(name, 1, 50000, 50, \
+ base::HistogramBase::kUmaTargetedHistogramFlag) \
+ ->Add((end.last_event_time - start.first_event_time).InMicroseconds());
+
void ComputeScrollLatencyHistograms(
const LatencyInfo::LatencyComponent& gpu_swap_begin_component,
const LatencyInfo::LatencyComponent& gpu_swap_end_component,
@@ -210,6 +237,92 @@ void ComputeScrollLatencyHistograms(
gpu_swap_end_component);
}
+void ComputeTouchAndWheelScrollLatencyHistograms(
+ const ui::LatencyInfo::LatencyComponent& gpu_swap_begin_component,
+ const ui::LatencyInfo::LatencyComponent& gpu_swap_end_component,
+ int64_t latency_component_id,
+ const ui::LatencyInfo& latency,
+ const std::string event_type_name) {
+ DCHECK(!latency.coalesced());
+ if (latency.coalesced())
+ return;
+
+ LatencyInfo::LatencyComponent original_component;
+ if (latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ latency_component_id, &original_component)) {
+ // This UMA metric tracks the time between the final frame swap for the
+ // first scroll event in a sequence and the original timestamp of that
+ // scroll event's underlying touch/wheel event.
+ UMA_HISTOGRAM_TOUCH_WHEEL_TO_SCROLL_LATENCY(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".TimeToFirstScrollUpdateSwapBegin2",
+ original_component, gpu_swap_begin_component);
+ } else if (latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ latency_component_id, &original_component)) {
+ // This UMA metric tracks the time from when the original touch event is
+ // created to when the scroll gesture results in final frame swap.
+ // First scroll events are excluded from this metric.
+ if (event_type_name == "Touch") {
+ UMA_HISTOGRAM_TOUCH_WHEEL_TO_SCROLL_LATENCY(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".TimeToScrollUpdateSwapBegin2",
+ original_component, gpu_swap_begin_component);
+ }
+ } else {
+ // No original component found.
+ return;
+ }
+
+ LatencyInfo::LatencyComponent rendering_scheduled_component;
+ bool rendering_scheduled_on_main = latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0,
+ &rendering_scheduled_component);
+ if (!rendering_scheduled_on_main) {
+ if (!latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
+ &rendering_scheduled_component))
+ return;
+ }
+
+ const std::string thread_name = rendering_scheduled_on_main ? "Main" : "Impl";
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".TimeToHandled2_" + thread_name,
+ original_component, rendering_scheduled_component);
+
+ LatencyInfo::LatencyComponent renderer_swap_component;
+ if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
+ &renderer_swap_component))
+ return;
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".HandledToRendererSwap2_" + thread_name,
+ rendering_scheduled_component, renderer_swap_component);
+
+ LatencyInfo::LatencyComponent browser_received_swap_component;
+ if (!latency.FindLatency(
+ ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0,
+ &browser_received_swap_component))
+ return;
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".RendererSwapToBrowserNotified2",
+ renderer_swap_component, browser_received_swap_component);
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
+ "Event.Latency.ScrollUpdate." + event_type_name +
+ ".BrowserNotifiedToBeforeGpuSwap2",
+ browser_received_swap_component, gpu_swap_begin_component);
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
+ "Event.Latency.ScrollUpdate." + event_type_name + ".GpuSwap2",
+ gpu_swap_begin_component, gpu_swap_end_component);
+}
// LatencyComponents generated in the renderer must have component IDs
// provided to them by the browser process. This function adds the correct
// component ID where necessary.
@@ -555,15 +668,6 @@ void RenderWidgetHostLatencyTracker::OnSwapCompositorFrame(
void RenderWidgetHostLatencyTracker::OnFrameSwapped(
const LatencyInfo& latency,
bool is_running_navigation_hint_task) {
- // Don't report frame latency on wheel events. Previously they were only
- // reported on touch metrics and we need to be consistent across reporting
- // metrics.
- LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component;
- if (latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
- &mouse_wheel_scroll_update_component)) {
- return;
- }
LatencyInfo::LatencyComponent gpu_swap_end_component;
if (!latency.FindLatency(
@@ -593,9 +697,26 @@ void RenderWidgetHostLatencyTracker::OnFrameSwapped(
return;
}
- ComputeScrollLatencyHistograms(gpu_swap_begin_component,
- gpu_swap_end_component, latency_component_id_,
- latency, is_running_navigation_hint_task);
+ ui::SourceEventType source_event_type = latency.source_event_type();
+ if (source_event_type == ui::SourceEventType::WHEEL ||
+ source_event_type == ui::SourceEventType::TOUCH) {
+ ComputeTouchAndWheelScrollLatencyHistograms(
+ gpu_swap_begin_component, gpu_swap_end_component, latency_component_id_,
+ latency,
+ source_event_type == ui::SourceEventType::WHEEL ? "Wheel" : "Touch");
+ }
+
+ // Compute the old scroll update latency metrics. They are exclusively
+ // calculated for touch scrolls, and will be deprecated on M56.
+ // (https://crbug.com/649754)
+ LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component;
+ if (!latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
+ &mouse_wheel_scroll_update_component)) {
+ ComputeScrollLatencyHistograms(
+ gpu_swap_begin_component, gpu_swap_end_component, latency_component_id_,
+ latency, is_running_navigation_hint_task);
+ }
}
} // namespace content
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 f75acf43d27..549945ece38 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
@@ -16,37 +16,44 @@ using testing::ElementsAre;
namespace content {
namespace {
-void AddFakeComponents(const RenderWidgetHostLatencyTracker& tracker,
- ui::LatencyInfo* latency) {
+void AddFakeComponentsWithTimeStamp(
+ const RenderWidgetHostLatencyTracker& tracker,
+ ui::LatencyInfo* latency,
+ base::TimeTicks time_stamp) {
+ latency->AddLatencyNumberWithTimestamp(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
+ 0, 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0, base::TimeTicks::Now(), 1);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, time_stamp,
+ 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
- latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), 0, base::TimeTicks::Now(), 1);
+ tracker.latency_component_id(), 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
+ time_stamp, 1);
+}
+
+void AddFakeComponents(const RenderWidgetHostLatencyTracker& tracker,
+ ui::LatencyInfo* latency) {
+ AddFakeComponentsWithTimeStamp(tracker, latency, base::TimeTicks::Now());
}
-void AddRenderingScheduledComponent(ui::LatencyInfo* latency, bool main) {
+void AddRenderingScheduledComponent(ui::LatencyInfo* latency,
+ bool main,
+ base::TimeTicks time_stamp) {
if (main) {
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
+ time_stamp, 1);
} else {
- latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, 0,
- base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, 0,
+ time_stamp, 1);
}
}
@@ -88,19 +95,74 @@ class RenderWidgetHostLatencyTrackerTest : public testing::Test {
std::unique_ptr<base::HistogramTester> histogram_tester_;
RenderWidgetHostLatencyTracker tracker_;
};
+TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelHistograms) {
+ for (bool rendering_on_main : {false, true}) {
+ for (bool is_running_navigation_hint_task : {false, true}) {
+ ResetHistograms();
+ {
+ auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
+ blink::WebMouseWheelEvent::PhaseChanged);
+ base::TimeTicks now = base::TimeTicks::Now();
+ wheel.timeStampSeconds = (now - base::TimeTicks()).InSecondsF();
+ ui::LatencyInfo wheel_latency(ui::SourceEventType::WHEEL);
+ AddFakeComponentsWithTimeStamp(*tracker(), &wheel_latency, now);
+ AddRenderingScheduledComponent(&wheel_latency, rendering_on_main, now);
+ tracker()->OnInputEvent(wheel, &wheel_latency);
+ EXPECT_TRUE(wheel_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+ EXPECT_TRUE(wheel_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_EQ(1U, wheel_latency.input_coordinates_size());
+ tracker()->OnInputEventAck(wheel, &wheel_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ tracker()->OnFrameSwapped(wheel_latency,
+ is_running_navigation_hint_task);
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelUI", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelAcked", 1));
+
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.Wheel."
+ "TimeToFirstScrollUpdateSwapBegin2",
+ 1));
+
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.TimeToHandled2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.TimeToHandled2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.HandledToRendererSwap2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.HandledToRendererSwap2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.RendererSwapToBrowserNotified2",
+ 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Wheel.BrowserNotifiedToBeforeGpuSwap2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.Wheel.GpuSwap2", 1));
+ }
+ }
+ }
+}
-TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
- for (bool rendering_on_main : { false, true }) {
+TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchHistograms) {
+ for (bool rendering_on_main : {false, true}) {
for (bool is_running_navigation_hint_task : {false, true}) {
ResetHistograms();
{
auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, blink::WebGestureDeviceTouchscreen);
- scroll.timeStampSeconds =
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+ base::TimeTicks now = base::TimeTicks::Now();
+ scroll.timeStampSeconds = (now - base::TimeTicks()).InSecondsF();
ui::LatencyInfo scroll_latency;
- AddFakeComponents(*tracker(), &scroll_latency);
- AddRenderingScheduledComponent(&scroll_latency, rendering_on_main);
+ AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
+ AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
@@ -113,31 +175,13 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
}
{
- auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
- blink::WebMouseWheelEvent::PhaseChanged);
- wheel.timeStampSeconds =
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
- ui::LatencyInfo wheel_latency;
- AddFakeComponents(*tracker(), &wheel_latency);
- AddRenderingScheduledComponent(&wheel_latency, rendering_on_main);
- tracker()->OnInputEvent(wheel, &wheel_latency);
- EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
- EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
- EXPECT_EQ(1U, wheel_latency.input_coordinates_size());
- tracker()->OnInputEventAck(wheel, &wheel_latency,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- }
-
- {
SyntheticWebTouchEvent touch;
touch.PressPoint(0, 0);
touch.PressPoint(1, 1);
- ui::LatencyInfo touch_latency;
- AddFakeComponents(*tracker(), &touch_latency);
- AddRenderingScheduledComponent(&touch_latency, rendering_on_main);
+ ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH);
+ base::TimeTicks now = base::TimeTicks::Now();
+ AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, now);
+ AddRenderingScheduledComponent(&touch_latency, rendering_on_main, now);
tracker()->OnInputEvent(touch, &touch_latency);
EXPECT_TRUE(touch_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
@@ -151,9 +195,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
is_running_navigation_hint_task);
}
- EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelUI", 1));
EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchUI", 1));
- EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelAcked", 1));
EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchAcked", 1));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.TouchToFirstScrollUpdateSwapBegin", 1));
@@ -184,6 +226,33 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap", 1));
EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToFirstScrollUpdateSwapBegin2",
+ 1));
+
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", 0));
+
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToHandled2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToHandled2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.HandledToRendererSwap2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.HandledToRendererSwap2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.RendererSwapToBrowserNotified2",
+ 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.BrowserNotifiedToBeforeGpuSwap2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.Touch.GpuSwap2", 1));
}
}
}
diff --git a/chromium/content/browser/renderer_host/input/stylus_text_selector.cc b/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
index 5af89606c47..a9bff878be7 100644
--- a/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
+++ b/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
@@ -89,6 +89,11 @@ bool StylusTextSelector::OnTouchEvent(const MotionEvent& event) {
case MotionEvent::ACTION_POINTER_DOWN:
break;
case MotionEvent::ACTION_NONE:
+ case MotionEvent::ACTION_HOVER_ENTER:
+ case MotionEvent::ACTION_HOVER_EXIT:
+ case MotionEvent::ACTION_HOVER_MOVE:
+ case MotionEvent::ACTION_BUTTON_PRESS:
+ case MotionEvent::ACTION_BUTTON_RELEASE:
NOTREACHED();
break;
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index c2e16707f9d..e7c49476199 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -32,7 +32,7 @@
#include "content/public/test/test_browser_context.h"
#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d.h"
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 c132d0b65ab..7c34adf3430 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
@@ -7,7 +7,7 @@
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "jni/MotionEventSynthesizer_jni.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/android/view_configuration.h"
using blink::WebTouchEvent;
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 54827094336..f1b4b0b45ac 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
@@ -14,8 +14,6 @@
namespace content {
-class ContentViewCoreImpl;
-
class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
public:
SyntheticGestureTargetAndroid(
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
index a4964bab259..fc5429e76c3 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
@@ -12,11 +12,6 @@
namespace aura {
class Window;
-class WindowEventDispatcher;
-
-namespace client {
-class ScreenPositionClient;
-}
} // namespace aura
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index c21b88bf983..ae8f7e128e3 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -8,7 +8,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/input_messages.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event.h"
#include "ui/events/latency_info.h"
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer.cc
index f840c15bbdd..46d801df10d 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer.cc
@@ -7,7 +7,7 @@
#include "base/memory/ptr_util.h"
#include "content/browser/renderer_host/input/synthetic_mouse_pointer.h"
#include "content/browser/renderer_host/input/synthetic_touch_pointer.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
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 a701ce51f02..51453d63938 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -5,7 +5,7 @@
#include "content/browser/renderer_host/input/synthetic_pointer_action.h"
#include "base/logging.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/latency_info.h"
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 e4b0f9d22f7..334a163d5dc 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
@@ -9,7 +9,7 @@
#include "content/browser/renderer_host/input/synthetic_pointer_action.h"
#include "content/browser/renderer_host/input/synthetic_touch_pointer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
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 b370ff5a117..3a79f498f0f 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
@@ -15,7 +15,7 @@
#include "content/common/content_export.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
index 46dc23aeab4..4c19027d923 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
@@ -5,7 +5,7 @@
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
#include "base/logging.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/latency_info.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h
index d2097634e43..761940f5024 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h
@@ -12,7 +12,7 @@
#include "content/common/content_export.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h
index de538912c3b..610e9c39da3 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h
@@ -13,7 +13,7 @@
#include "content/common/content_export.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
index b63e2f76487..d17be7a27c1 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -30,7 +30,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/event_switches.h"
#include "ui/events/latency_info.h"
@@ -165,7 +165,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
// main thread was in a busy loop.
while (wait_until_scrolled &&
frame_watcher->LastMetadata().root_scroll_offset.y() <
- distance.y()) {
+ (distance.y() / 2)) {
frame_watcher->WaitFrames(1);
}
@@ -175,7 +175,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
return false;
// Allow for 1px rounding inaccuracies for some screen sizes.
- EXPECT_NEAR(distance.y(), scrollTop, 1);
+ EXPECT_LT(distance.y() / 2, scrollTop);
return true;
}
@@ -188,15 +188,11 @@ class TouchActionBrowserTest : public ContentBrowserTest {
// Mac doesn't yet have a gesture recognizer, so can't support turning touch
// events into scroll gestures.
// Will be fixed with http://crbug.com/337142
-#if defined(OS_MACOSX)
-#define MAYBE_DefaultAuto DISABLED_DefaultAuto
-#else
-#define MAYBE_DefaultAuto DefaultAuto
-#endif
+// Flaky on all platforms: https://crbug.com/376668
//
// Verify the test infrastructure works - we can touch-scroll the page and get a
// touchcancel as expected.
-IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_DefaultAuto) {
LoadURL();
bool scrolled = DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45), true);
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 d2bae4e003b..8f87bc061c4 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -7,7 +7,7 @@
#include <math.h>
#include "base/logging.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
using blink::WebInputEvent;
using blink::WebGestureEvent;
@@ -96,11 +96,11 @@ bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
return drop_pinch_gesture_events_;
case WebInputEvent::GesturePinchEnd:
- // TODO(mustaq): Don't reset drop_pinch_gesture_events_ here because a
- // pinch-zoom-out-then-zoom-in sends two separate pinch sequences within a
- // single gesture-scroll sequence, see crbug.com/662047#c13. Is it
- // expected?
- return drop_pinch_gesture_events_;
+ if (drop_pinch_gesture_events_) {
+ drop_pinch_gesture_events_ = false;
+ return true;
+ }
+ break;
// The double tap gesture is a tap ending event. If a double tap gesture is
// filtered out, replace it with a tap event.
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 115d083ec1b..7647a791481 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
@@ -7,7 +7,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
using blink::WebGestureEvent;
using blink::WebInputEvent;
@@ -423,9 +423,6 @@ TEST(TouchActionFilterTest, Pinch) {
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.
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index 48ba8b5102d..187dee792f3 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -11,7 +11,7 @@
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/input/input_event_ack_state.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/gfx/geometry/size_f.h"
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_client.h b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
index 89ce509ab98..6295372db1f 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_client.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
@@ -7,7 +7,8 @@
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.cc b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
index 5aea8990531..d945bb9ae56 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -8,8 +8,8 @@
#include "base/auto_reset.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/common/input/web_touch_event_traits.h"
@@ -261,7 +261,6 @@ class TouchEventQueue::TouchTimeoutHandler {
return pending_ack_state_ != PENDING_ACK_NONE;
}
-
TouchEventQueue* touch_queue_;
// How long to wait on a touch ack before cancelling the touch sequence.
@@ -451,8 +450,6 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
}
TouchEventQueue::~TouchEventQueue() {
- if (!touch_queue_.empty())
- base::STLDeleteElements(&touch_queue_);
}
void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
@@ -475,7 +472,8 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
// There is no touch event in the queue. Forward it to the renderer
// immediately.
- touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
+ touch_queue_.push_back(
+ base::MakeUnique<CoalescedWebTouchEvent>(event, false));
ForwardNextEventToRenderer();
return;
}
@@ -483,11 +481,12 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
// If the last queued touch-event was a touch-move, and the current event is
// also a touch-move, then the events can be coalesced into a single event.
if (touch_queue_.size() > 1) {
- CoalescedWebTouchEvent* last_event = touch_queue_.back();
+ CoalescedWebTouchEvent* last_event = touch_queue_.back().get();
if (last_event->CoalesceEventIfPossible(event))
return;
}
- touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
+ touch_queue_.push_back(
+ base::MakeUnique<CoalescedWebTouchEvent>(event, false));
}
void TouchEventQueue::PrependTouchScrollNotification() {
@@ -513,7 +512,8 @@ void TouchEventQueue::PrependTouchScrollNotification() {
auto it = touch_queue_.begin();
DCHECK(it != touch_queue_.end());
- touch_queue_.insert(++it, new CoalescedWebTouchEvent(touch, false));
+ touch_queue_.insert(++it,
+ base::MakeUnique<CoalescedWebTouchEvent>(touch, false));
}
}
@@ -660,7 +660,8 @@ void TouchEventQueue::FlushPendingAsyncTouchmove() {
std::unique_ptr<TouchEventWithLatencyInfo> touch =
std::move(pending_async_touchmove_);
touch->event.dispatchType = WebInputEvent::EventNonBlocking;
- touch_queue_.push_front(new CoalescedWebTouchEvent(*touch, true));
+ touch_queue_.push_front(
+ base::MakeUnique<CoalescedWebTouchEvent>(*touch, true));
SendTouchEventImmediately(touch.get());
}
@@ -770,7 +771,8 @@ void TouchEventQueue::AckTouchEventToClient(
NOTREACHED() << "Too many acks";
return;
}
- std::unique_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
+ std::unique_ptr<CoalescedWebTouchEvent> acked_event =
+ std::move(touch_queue_.front());
DCHECK(acked_event);
UpdateTouchConsumerStates(acked_event->coalesced_event().event, ack_result);
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.h b/chromium/content/browser/renderer_host/input/touch_event_queue.h
index 31a69fcb18e..f039e14aec2 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -10,13 +10,14 @@
#include <deque>
#include <list>
+#include <memory>
#include "base/macros.h"
#include "base/time/time.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 "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/point_f.h"
namespace content {
@@ -183,8 +184,7 @@ class CONTENT_EXPORT TouchEventQueue {
// Handles touch event forwarding and ack'ed event dispatch.
TouchEventQueueClient* client_;
- typedef std::list<CoalescedWebTouchEvent*> TouchQueue;
- TouchQueue touch_queue_;
+ std::list<std::unique_ptr<CoalescedWebTouchEvent>> touch_queue_;
// Position of the first touch in the most recent sequence forwarded to the
// client.
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
index 580e9a78b38..d439f219069 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
@@ -19,7 +19,7 @@
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input/web_touch_event_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
using blink::WebGestureEvent;
using blink::WebInputEvent;
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index 9ee782e9d20..05a0505f17a 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -23,7 +23,7 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/event_switches.h"
#include "ui/events/latency_info.h"
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 6b9fbdca608..c1a86f8d6c2 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,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.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/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -168,6 +169,7 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
new TestTouchSelectionControllerClientAura(rwhva);
rwhva->SetSelectionControllerClientForTest(
base::WrapUnique(selection_controller_client_));
+ rwhva->event_handler()->disable_input_event_router_for_testing();
}
private:
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
index 49719639452..1934ad6e863 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
@@ -10,7 +10,7 @@
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
index 016665399a4..9e893110611 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -112,32 +112,39 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(
}
WebMouseEvent WebMouseEventBuilder::Build(
- WebInputEvent::Type type,
- WebMouseEvent::Button button,
- double time_sec,
- int window_x,
- int window_y,
- int modifiers,
- int click_count,
- WebPointerProperties::PointerType pointer_type) {
+ WebInputEvent::Type type,
+ double time_sec,
+ int window_x,
+ int window_y,
+ int modifiers,
+ int click_count,
+ int pointer_id,
+ float pressure,
+ float orientation_rad,
+ float tilt_rad,
+ int changed_button,
+ int tool_type) {
DCHECK(WebInputEvent::isMouseEventType(type));
WebMouseEvent result;
result.type = type;
- result.pointerType = pointer_type;
result.x = window_x;
result.y = window_y;
result.windowX = window_x;
result.windowY = window_y;
result.timeStampSeconds = time_sec;
result.clickCount = click_count;
- result.modifiers = modifiers;
-
- if (type == WebInputEvent::MouseDown || type == WebInputEvent::MouseUp)
- result.button = button;
- else
- result.button = WebMouseEvent::Button::NoButton;
+ result.modifiers = ui::EventFlagsToWebEventModifiers(modifiers);
+
+ ui::SetWebPointerPropertiesFromMotionEventData(
+ result,
+ pointer_id,
+ pressure,
+ orientation_rad,
+ tilt_rad,
+ changed_button,
+ tool_type);
return result;
}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
index b6bcf44c7e1..ffba9822bd8 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -9,11 +9,8 @@
#include "base/android/scoped_java_ref.h"
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace ui {
-class MotionEventAndroid;
-}
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
@@ -21,13 +18,17 @@ class WebMouseEventBuilder {
public:
static blink::WebMouseEvent Build(
blink::WebInputEvent::Type type,
- blink::WebMouseEvent::Button button,
double time_sec,
int window_x,
int window_y,
int modifiers,
int click_count,
- blink::WebPointerProperties::PointerType pointer_type);
+ int pointer_id,
+ float pressure,
+ float orientation_rad,
+ float tilt_rad,
+ int changed_button,
+ int tool_type);
};
class WebMouseWheelEventBuilder {
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
index d5cbebdc10e..1edee9ba72e 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
@@ -9,7 +9,7 @@
#include "base/android/jni_android.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/android/key_event_utils.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/keycodes/dom/dom_code.h"
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
index dbab1d88e12..03a3d6ca0ef 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.h
@@ -6,7 +6,8 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_MAC_H_
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
@class NSEvent;
@class NSView;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
index 45c37416b0d..41a9d27b9d5 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -37,7 +37,7 @@
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/string_util.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/events/blink/blink_event_util.h"
#import "ui/events/cocoa/cocoa_event_utils.h"
@@ -48,79 +48,6 @@ namespace content {
namespace {
-// Return true if the target modifier key is up. OS X has an "official" flag
-// to test whether either left or right versions of a modifier key are held,
-// and "unofficial" flags for the left and right versions independently. This
-// function verifies that |target_key_mask| and |otherKeyMask| (which should be
-// the left and right versions of a modifier) are consistent with with the
-// state of |eitherKeyMask| (which should be the corresponding ""official"
-// flag). If they are consistent, it tests |target_key_mask|; otherwise it tests
-// |either_key_mask|.
-inline bool IsModifierKeyUp(unsigned int flags,
- unsigned int target_key_mask,
- unsigned int other_key_mask,
- unsigned int either_key_mask) {
- bool either_key_down = (flags & either_key_mask) != 0;
- bool target_key_down = (flags & target_key_mask) != 0;
- bool other_key_down = (flags & other_key_mask) != 0;
- if (either_key_down != (target_key_down || other_key_down))
- return !either_key_down;
- return !target_key_down;
-}
-
-bool IsKeyUpEvent(NSEvent* event) {
- if ([event type] != NSFlagsChanged)
- return [event type] == NSKeyUp;
-
- // Unofficial bit-masks for left- and right-hand versions of modifier keys.
- // These values were determined empirically.
- const unsigned int kLeftControlKeyMask = 1 << 0;
- const unsigned int kLeftShiftKeyMask = 1 << 1;
- const unsigned int kRightShiftKeyMask = 1 << 2;
- const unsigned int kLeftCommandKeyMask = 1 << 3;
- const unsigned int kRightCommandKeyMask = 1 << 4;
- const unsigned int kLeftAlternateKeyMask = 1 << 5;
- const unsigned int kRightAlternateKeyMask = 1 << 6;
- const unsigned int kRightControlKeyMask = 1 << 13;
-
- switch ([event keyCode]) {
- case 54: // Right Command
- return IsModifierKeyUp([event modifierFlags], kRightCommandKeyMask,
- kLeftCommandKeyMask, NSCommandKeyMask);
- case 55: // Left Command
- return IsModifierKeyUp([event modifierFlags], kLeftCommandKeyMask,
- kRightCommandKeyMask, NSCommandKeyMask);
-
- case 57: // Capslock
- return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
-
- case 56: // Left Shift
- return IsModifierKeyUp([event modifierFlags], kLeftShiftKeyMask,
- kRightShiftKeyMask, NSShiftKeyMask);
- case 60: // Right Shift
- return IsModifierKeyUp([event modifierFlags], kRightShiftKeyMask,
- kLeftShiftKeyMask, NSShiftKeyMask);
-
- case 58: // Left Alt
- return IsModifierKeyUp([event modifierFlags], kLeftAlternateKeyMask,
- kRightAlternateKeyMask, NSAlternateKeyMask);
- case 61: // Right Alt
- return IsModifierKeyUp([event modifierFlags], kRightAlternateKeyMask,
- kLeftAlternateKeyMask, NSAlternateKeyMask);
-
- case 59: // Left Ctrl
- return IsModifierKeyUp([event modifierFlags], kLeftControlKeyMask,
- kRightControlKeyMask, NSControlKeyMask);
- case 62: // Right Ctrl
- return IsModifierKeyUp([event modifierFlags], kRightControlKeyMask,
- kLeftControlKeyMask, NSControlKeyMask);
-
- case 63: // Function
- return ([event modifierFlags] & NSFunctionKeyMask) == 0;
- }
- return false;
-}
-
inline NSString* FilterSpecialCharacter(NSString* str) {
if ([str length] != 1)
return str;
@@ -276,8 +203,8 @@ ui::DomKey DomKeyFromEvent(NSEvent* event) {
blink::WebKeyboardEvent WebKeyboardEventBuilder::Build(NSEvent* event) {
blink::WebKeyboardEvent result;
- result.type = IsKeyUpEvent(event) ? blink::WebInputEvent::KeyUp
- : blink::WebInputEvent::RawKeyDown;
+ result.type = ui::IsKeyUpEvent(event) ? blink::WebInputEvent::KeyUp
+ : blink::WebInputEvent::RawKeyDown;
result.modifiers = ModifiersFromEvent(event);
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
index 7866c651a34..9ffb94f0273 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
@@ -7,6 +7,7 @@
#include <array>
#include <utility>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/sys_byteorder.h"
#include "content/public/browser/browser_thread.h"
#include "media/base/audio_bus.h"
@@ -127,36 +128,78 @@ void WriteWavHeader(WavHeaderBuffer* buf,
} // namespace
-AudioInputDebugWriter::AudioInputDebugWriter(
- base::File file,
+// Manages the debug recording file and writes to it. Can be created on any
+// thread. All the operations must be executed on FILE thread. Must be destroyed
+// on FILE thread.
+class AudioInputDebugWriter::AudioFileWriter {
+ public:
+ static AudioFileWriterUniquePtr Create(const base::FilePath& file_name,
+ const media::AudioParameters& params);
+
+ ~AudioFileWriter();
+
+ // Write data from |data| to file.
+ void Write(const media::AudioBus* data);
+
+ private:
+ AudioFileWriter(const media::AudioParameters& params);
+
+ // Write wave header to file. Called on the FILE thread twice: on construction
+ // of AudioFileWriter size of the wave data is unknown, so the header is
+ // written with zero sizes; then on destruction it is re-written with the
+ // actual size info accumulated throughout the object lifetime.
+ void WriteHeader();
+
+ void CreateRecordingFile(const base::FilePath& file_name);
+
+ // The file to write to.
+ base::File file_;
+
+ // Number of written samples.
+ uint64_t samples_;
+
+ // Input audio parameters required to build wave header.
+ const media::AudioParameters params_;
+
+ // Intermediate buffer to be written to file. Interleaved 16 bit audio data.
+ std::unique_ptr<int16_t[]> interleaved_data_;
+ int interleaved_data_size_;
+};
+
+// static
+AudioInputDebugWriter::AudioFileWriterUniquePtr
+AudioInputDebugWriter::AudioFileWriter::Create(
+ const base::FilePath& file_name,
+ const media::AudioParameters& params) {
+ AudioFileWriterUniquePtr file_writer(new AudioFileWriter(params));
+
+ // base::Unretained is safe, because destructor is called on FILE thread or on
+ // FILE message loop destruction.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&AudioFileWriter::CreateRecordingFile,
+ base::Unretained(file_writer.get()), file_name));
+ return file_writer;
+}
+
+AudioInputDebugWriter::AudioFileWriter::AudioFileWriter(
const media::AudioParameters& params)
- : file_(std::move(file)),
- samples_(0),
- params_(params),
- interleaved_data_size_(0),
- weak_factory_(this) {
+ : samples_(0), params_(params), interleaved_data_size_(0) {
DCHECK_EQ(params.bits_per_sample(), kBytesPerSample * 8);
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&AudioInputDebugWriter::WriteHeader,
- weak_factory_.GetWeakPtr()));
}
-AudioInputDebugWriter::~AudioInputDebugWriter() {
+AudioInputDebugWriter::AudioFileWriter::~AudioFileWriter() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- WriteHeader();
+ if (file_.IsValid())
+ WriteHeader();
}
-void AudioInputDebugWriter::Write(std::unique_ptr<media::AudioBus> data) {
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&AudioInputDebugWriter::DoWrite,
- weak_factory_.GetWeakPtr(),
- base::Passed(&data)));
-}
-
-void AudioInputDebugWriter::DoWrite(std::unique_ptr<media::AudioBus> data) {
+void AudioInputDebugWriter::AudioFileWriter::Write(
+ const media::AudioBus* data) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ if (!file_.IsValid())
+ return;
+
// Convert to 16 bit audio and write to file.
int data_size = data->frames() * data->channels();
if (!interleaved_data_ || interleaved_data_size_ < data_size) {
@@ -178,13 +221,10 @@ void AudioInputDebugWriter::DoWrite(std::unique_ptr<media::AudioBus> data) {
data_size * sizeof(interleaved_data_[0]));
}
-// This method is called twice: on construction of AudioInputDebugWriter size of
-// the data is unknown, so the header is written with zero sizes; then on
-// destruction it is re-written with the actual size info accumulated throughout
-// its lifetime.
-void AudioInputDebugWriter::WriteHeader() {
+void AudioInputDebugWriter::AudioFileWriter::WriteHeader() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-
+ if (!file_.IsValid())
+ return;
WavHeaderBuffer buf;
WriteWavHeader(&buf, params_.channels(), params_.sample_rate(), samples_);
file_.Write(0, &buf[0], kWavHeaderSize);
@@ -194,4 +234,73 @@ void AudioInputDebugWriter::WriteHeader() {
file_.Seek(base::File::FROM_BEGIN, kWavHeaderSize);
}
+void AudioInputDebugWriter::AudioFileWriter::CreateRecordingFile(
+ const base::FilePath& file_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(!file_.IsValid());
+
+ file_ = base::File(file_name,
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+
+ if (file_.IsValid()) {
+ WriteHeader();
+ return;
+ }
+
+ // Note that we do not inform AudioInputDebugWriter that the file creation
+ // fails, so it will continue to post data to be recorded, which won't
+ // be written to the file. This also won't be reflected in WillWrite(). It's
+ // fine, because this situation is rare, and all the posting is expected to
+ // happen in case of success anyways. This allows us to save on thread hops
+ // for error reporting and to avoid dealing with lifetime issues. It also
+ // means file_.IsValid() should always be checked before issuing writes to it.
+ PLOG(ERROR) << "Could not open debug recording file, error="
+ << file_.error_details();
+}
+
+AudioInputDebugWriter::AudioInputDebugWriter(
+ const media::AudioParameters& params)
+ : params_(params) {
+ client_sequence_checker_.DetachFromSequence();
+}
+
+AudioInputDebugWriter::~AudioInputDebugWriter() {
+ // |file_writer_| will be deleted on FILE thread.
+}
+
+void AudioInputDebugWriter::Start(const base::FilePath& file_name) {
+ DCHECK(client_sequence_checker_.CalledOnValidSequence());
+ DCHECK(!file_writer_);
+ file_writer_ = AudioFileWriter::Create(file_name, params_);
+}
+
+void AudioInputDebugWriter::Stop() {
+ DCHECK(client_sequence_checker_.CalledOnValidSequence());
+ // |file_writer_| is deleted on FILE thread.
+ file_writer_.reset();
+ client_sequence_checker_.DetachFromSequence();
+}
+
+void AudioInputDebugWriter::Write(std::unique_ptr<media::AudioBus> data) {
+ DCHECK(client_sequence_checker_.CalledOnValidSequence());
+ if (!file_writer_)
+ return;
+
+ // base::Unretained for |file_writer_| is safe, see the destructor.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ // Callback takes ownership of |data|:
+ base::Bind(&AudioFileWriter::Write, base::Unretained(file_writer_.get()),
+ base::Owned(data.release())));
+}
+
+bool AudioInputDebugWriter::WillWrite() {
+ // Note that if this is called from any place other than
+ // |client_sequence_checker_| then there is a data race here, but it's fine,
+ // because Write() will check for |file_writer_|. So, we are not very precise
+ // here, but it's fine: we can afford missing some data or scheduling some
+ // no-op writes.
+ return !!file_writer_;
+}
+
} // namspace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
index 3525ec8c69d..c618667ce05 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
@@ -11,59 +11,40 @@
#include "base/files/file.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
#include "media/audio/audio_input_writer.h"
#include "media/base/audio_parameters.h"
namespace media {
class AudioBus;
-class AudioBusRefCounted;
} // namespace media
namespace content {
-// Writes audio input data used for debugging purposes. Can be created on any
-// thread. Must be destroyed on the FILE thread. Write call can be made on any
-// thread. This object must be unregistered in Write caller before destroyed.
-// When created, it takes ownership of |file|.
+// Writes audio input data used for debugging purposes. All operations are
+// non-blocking.
class CONTENT_EXPORT AudioInputDebugWriter
: public NON_EXPORTED_BASE(media::AudioInputWriter) {
public:
- AudioInputDebugWriter(base::File file, const media::AudioParameters& params);
-
+ explicit AudioInputDebugWriter(const media::AudioParameters& params);
~AudioInputDebugWriter() override;
- // Write data from |data| to file.
+ void Start(const base::FilePath& file) override;
+ void Stop() override;
void Write(std::unique_ptr<media::AudioBus> data) override;
+ bool WillWrite() override;
private:
- // Write data from |data| to file. Called on the FILE thread.
- void DoWrite(std::unique_ptr<media::AudioBus> data);
-
- // Write wave header to file. Called on the FILE thread twice: on construction
- // of AudioInputDebugWriter size of the wave data is unknown, so the header is
- // written with zero sizes; then on destruction it is re-written with the
- // actual size info accumulated throughout the object lifetime.
- void WriteHeader();
-
- // The file to write to.
- base::File file_;
-
- // Number of written samples.
- uint64_t samples_;
-
- // Input audio parameters required to build wave header.
- media::AudioParameters params_;
-
- // Intermediate buffer to be written to file. Interleaved 16 bit audio data.
- std::unique_ptr<int16_t[]> interleaved_data_;
- int interleaved_data_size_;
-
- base::WeakPtrFactory<AudioInputDebugWriter> weak_factory_;
+ class AudioFileWriter;
+ using AudioFileWriterUniquePtr =
+ std::unique_ptr<AudioFileWriter, BrowserThread::DeleteOnFileThread>;
+ AudioFileWriterUniquePtr file_writer_;
+ const media::AudioParameters params_;
+ base::SequenceChecker client_sequence_checker_;
};
} // namspace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc
index ee8b5d5cdfd..d2212ec3501 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc
@@ -5,6 +5,8 @@
#include <stdint.h>
#include "base/files/file_util.h"
+#include "base/memory/ptr_util.h"
+#include "base/synchronization/waitable_event.h"
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/media/audio_input_debug_writer.h"
#include "content/public/browser/browser_thread.h"
@@ -41,7 +43,8 @@ class AudioInputDebugWriterTest
: public testing::TestWithParam<AudioInputDebugWriterTestData> {
public:
AudioInputDebugWriterTest()
- : params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR,
+ : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD),
+ params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR,
std::tr1::get<0>(GetParam()),
std::tr1::get<1>(GetParam()),
kBytesPerSample * 8,
@@ -152,17 +155,10 @@ class AudioInputDebugWriterTest
void TestDoneOnFileThread(const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- // |writer| must be destroyed on FILE thread.
- input_debug_writer_.reset(nullptr);
callback.Run();
}
- void DoDebugRecording(base::File file) {
- if (!file.IsValid())
- return;
-
- input_debug_writer_.reset(
- new AudioInputDebugWriter(std::move(file), params_));
+ void DoDebugRecording() {
// Write tasks are posted to BrowserThread::FILE.
for (int i = 0; i < writes_; ++i) {
std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create(
@@ -175,7 +171,9 @@ class AudioInputDebugWriterTest
input_debug_writer_->Write(std::move(bus));
}
+ }
+ void WaitForRecordingCompletion() {
media::WaitableMessageLoopEvent event;
// Post a task to BrowserThread::FILE indicating that all the writes are
@@ -189,6 +187,28 @@ class AudioInputDebugWriterTest
event.RunAndWait();
}
+ void RecordAndVerifyOnce() {
+ base::FilePath file_path;
+ EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
+
+ input_debug_writer_->Start(file_path);
+
+ DoDebugRecording();
+
+ input_debug_writer_->Stop();
+
+ WaitForRecordingCompletion();
+
+ VerifyRecording(file_path);
+
+ if (::testing::Test::HasFailure()) {
+ LOG(ERROR) << "Test failed; keeping recording(s) at ["
+ << file_path.value().c_str() << "].";
+ } else {
+ EXPECT_TRUE(base::DeleteFile(file_path, false));
+ }
+ }
+
protected:
TestBrowserThreadBundle thread_bundle_;
@@ -211,15 +231,37 @@ class AudioInputDebugWriterTest
DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest);
};
+class AudioInputDebugWriterBehavioralTest : public AudioInputDebugWriterTest {};
+
TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+
+ RecordAndVerifyOnce();
+}
+
+TEST_P(AudioInputDebugWriterBehavioralTest,
+ DeletedBeforeRecordingFinishedOnFileThread) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+
base::FilePath file_path;
EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
- base::File file(file_path,
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
+ base::WaitableEvent* wait_for_deletion =
+ new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&base::WaitableEvent::Wait, base::Owned(wait_for_deletion)));
+
+ input_debug_writer_->Start(file_path);
+
+ DoDebugRecording();
- DoDebugRecording(std::move(file));
+ input_debug_writer_.reset();
+ wait_for_deletion->Signal();
+
+ WaitForRecordingCompletion();
VerifyRecording(file_path);
@@ -231,10 +273,36 @@ TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) {
}
}
+TEST_P(AudioInputDebugWriterBehavioralTest, FileCreationError) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+ base::FilePath file_path; // Empty file name.
+ input_debug_writer_->Start(file_path);
+ DoDebugRecording();
+}
+
+TEST_P(AudioInputDebugWriterBehavioralTest, StartStopStartStop) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+ RecordAndVerifyOnce();
+ RecordAndVerifyOnce();
+}
+
+TEST_P(AudioInputDebugWriterBehavioralTest, DestroyNotStarted) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+ input_debug_writer_.reset();
+}
+
+TEST_P(AudioInputDebugWriterBehavioralTest, DestroyStarted) {
+ input_debug_writer_.reset(new AudioInputDebugWriter(params_));
+ base::FilePath file_path;
+ EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
+ input_debug_writer_->Start(file_path);
+ input_debug_writer_.reset();
+}
+
INSTANTIATE_TEST_CASE_P(
AudioInputDebugWriterTest,
AudioInputDebugWriterTest,
- // Using 10ms sframes per buffer everywhere.
+ // Using 10ms frames per buffer everywhere.
testing::Values(
// No writes.
std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
@@ -267,4 +335,15 @@ INSTANTIATE_TEST_CASE_P(
48000 / 100,
1500)));
+INSTANTIATE_TEST_CASE_P(
+ AudioInputDebugWriterBehavioralTest,
+ AudioInputDebugWriterBehavioralTest,
+ // Using 10ms frames per buffer everywhere.
+ testing::Values(
+ // No writes.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
+ 44100,
+ 44100 / 100,
+ 100)));
+
} // namespace content
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 ac6747c90ac..30260b10e6a 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
@@ -142,8 +142,8 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
"Media.AudioInputDeviceManager.OpenOnDeviceThreadTime");
DCHECK(IsOnDeviceThread());
- StreamDeviceInfo out(info.device.type, info.device.name, info.device.id,
- info.device.group_id, 0, 0, 0);
+ StreamDeviceInfo out(info.device.type, info.device.name, info.device.id, 0, 0,
+ 0);
out.session_id = session_id;
MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
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 c3aeef1561c..e31b3a7f493 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
@@ -176,10 +176,9 @@ TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenNotExistingDevice) {
MediaStreamType stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
std::string device_name("device_doesnt_exist");
std::string device_id("id_doesnt_exist");
- std::string group_id("group_doesnt_exist");
int sample_rate(0);
int channel_config(0);
- StreamDeviceInfo dummy_device(stream_type, device_name, device_id, group_id,
+ StreamDeviceInfo dummy_device(stream_type, device_name, device_id,
sample_rate, channel_config, 2048);
int session_id = manager_->Open(dummy_device);
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 9008596c5df..84d36838fb8 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
@@ -51,29 +51,6 @@ void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
DVLOG(1) << oss.str();
}
-#ifdef ENABLE_WEBRTC
-base::File CreateDebugRecordingFile(base::FilePath file_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- base::File recording_file(
- file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- PLOG_IF(ERROR, !recording_file.IsValid())
- << "Could not open debug recording file, error="
- << recording_file.error_details();
- return recording_file;
-}
-
-void CloseFile(base::File file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- // |file| must be closed and destroyed on FILE thread.
-}
-
-void DeleteInputDebugWriterOnFileThread(
- std::unique_ptr<AudioInputDebugWriter> writer) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- // |writer| must be closed and destroyed on FILE thread.
-}
-#endif // ENABLE_WEBRTC
-
} // namespace
struct AudioInputRendererHost::AudioEntry {
@@ -95,20 +72,11 @@ struct AudioInputRendererHost::AudioEntry {
// ownership of the writer.
std::unique_ptr<AudioInputSyncWriter> writer;
- // Must be deleted on the file thread. Must be posted for deletion and nulled
- // before the AudioEntry is deleted.
- std::unique_ptr<AudioInputDebugWriter> input_debug_writer;
-
// 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;
-
-#ifdef ENABLE_WEBRTC
- // Stream audio parameters, used to build wave header for debug recording.
- media::AudioParameters audio_params;
-#endif // ENABLE_WEBRTC
};
AudioInputRendererHost::AudioEntry::AudioEntry()
@@ -119,7 +87,6 @@ AudioInputRendererHost::AudioEntry::AudioEntry()
}
AudioInputRendererHost::AudioEntry::~AudioEntry() {
- DCHECK(!input_debug_writer.get());
}
AudioInputRendererHost::AudioInputRendererHost(
@@ -156,10 +123,7 @@ void AudioInputRendererHost::EnableDebugRecording(const base::FilePath& file) {
void AudioInputRendererHost::DisableDebugRecording() {
for (const auto& entry : audio_entries_) {
- entry.second->controller->DisableDebugRecording(
- base::Bind(&AudioInputRendererHost::DeleteDebugWriter,
- this,
- entry.first));
+ entry.second->controller->DisableDebugRecording();
}
}
#endif // ENABLE_WEBRTC
@@ -424,10 +388,17 @@ void AudioInputRendererHost::DoCreateStream(
return;
}
+#if defined(ENABLE_WEBRTC)
+ std::unique_ptr<media::AudioInputWriter> debug_writer(
+ new AudioInputDebugWriter(audio_params));
+#else
+ std::unique_ptr<media::AudioInputWriter> debug_writer(nullptr);
+#endif
+
// If we have successfully created the SyncWriter then assign it to the
// entry and construct an AudioInputController.
entry->writer.reset(writer.release());
- if (WebContentsMediaCaptureId::IsWebContentsDeviceId(device_id)) {
+ if (WebContentsMediaCaptureId::Parse(device_id, nullptr)) {
// For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
// window, we do not mute the source audio.
// For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
@@ -438,8 +409,8 @@ void AudioInputRendererHost::DoCreateStream(
audio_manager_->GetTaskRunner(), this,
WebContentsAudioInputStream::Create(
device_id, audio_params, audio_manager_->GetWorkerTaskRunner(),
- audio_mirroring_manager_, type == MEDIA_DESKTOP_AUDIO_CAPTURE),
- entry->writer.get(), user_input_monitor_);
+ audio_mirroring_manager_),
+ entry->writer.get(), std::move(debug_writer), user_input_monitor_);
// Only count for captures from desktop media picker dialog.
if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE)
IncrementDesktopCaptureCounter(TAB_AUDIO_CAPTURER_CREATED);
@@ -450,12 +421,8 @@ void AudioInputRendererHost::DoCreateStream(
// TODO(grunell): Clean up the low latency terminology so that it's less
// confusing.
entry->controller = media::AudioInputController::CreateLowLatency(
- audio_manager_,
- this,
- audio_params,
- device_id,
- entry->writer.get(),
- user_input_monitor_,
+ audio_manager_, this, audio_params, device_id, entry->writer.get(),
+ std::move(debug_writer), user_input_monitor_,
config.automatic_gain_control);
oss << ", AGC=" << config.automatic_gain_control;
@@ -482,10 +449,6 @@ void AudioInputRendererHost::DoCreateStream(
}
#endif
-#if defined(ENABLE_WEBRTC)
- entry->audio_params = audio_params;
-#endif // ENABLE_WEBRTC
-
MediaStreamManager::SendMessageToNativeLog(oss.str());
DVLOG(1) << oss.str();
@@ -587,15 +550,6 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
}
#endif
-#if defined(ENABLE_WEBRTC)
- if (entry->input_debug_writer.get()) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeleteInputDebugWriterOnFileThread,
- base::Passed(std::move(entry->input_debug_writer))));
- }
-#endif
-
// Delete the entry when this method goes out of scope.
std::unique_ptr<AudioEntry> entry_deleter(entry);
@@ -678,57 +632,19 @@ base::FilePath AudioInputRendererHost::GetDebugRecordingFilePathWithExtensions(
}
void AudioInputRendererHost::EnableDebugRecordingForId(
- const base::FilePath& file,
+ const base::FilePath& file_name,
int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(
- &CreateDebugRecordingFile,
- file.AddExtension(IntToStringType(stream_id))
- .AddExtension(kDebugRecordingFileNameExtension)),
- base::Bind(
- &AudioInputRendererHost::DoEnableDebugRecording,
- weak_factory_.GetWeakPtr(),
- stream_id));
-}
-
-#undef IntToStringType
-
-void AudioInputRendererHost::DoEnableDebugRecording(
- int stream_id,
- base::File file) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!file.IsValid())
- return;
AudioEntry* entry = LookupById(stream_id);
- if (!entry) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&CloseFile, Passed(std::move(file))));
+ if (!entry)
return;
- }
- entry->input_debug_writer.reset(
- new AudioInputDebugWriter(std::move(file), entry->audio_params));
- entry->controller->EnableDebugRecording(entry->input_debug_writer.get());
+ entry->controller->EnableDebugRecording(
+ file_name.AddExtension(IntToStringType(stream_id))
+ .AddExtension(kDebugRecordingFileNameExtension));
}
-void AudioInputRendererHost::DeleteDebugWriter(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- AudioEntry* entry = LookupById(stream_id);
- if (!entry) {
- // This happens if DisableDebugRecording is called right after
- // DeleteEntries.
- return;
- }
+#undef IntToStringType
- if (entry->input_debug_writer.get()) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeleteInputDebugWriterOnFileThread,
- base::Passed(std::move(entry->input_debug_writer))));
- }
-}
#endif // defined(ENABLE_WEBRTC)
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
index cd6ed9db082..4374632542a 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
@@ -46,7 +46,6 @@
namespace media {
class AudioManager;
-class AudioParameters;
class UserInputMonitor;
}
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 e706934dfbc..3bed1440595 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
@@ -9,6 +9,7 @@
#include "base/format_macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -119,6 +120,7 @@ void AudioInputSyncWriter::Write(const AudioBus* data,
double volume,
bool key_pressed,
uint32_t hardware_delay_bytes) {
+ TRACE_EVENT0("audio", "AudioInputSyncWriter::Write");
++write_count_;
CheckTimeSinceLastWrite();
@@ -171,6 +173,8 @@ void AudioInputSyncWriter::Write(const AudioBus* data,
if (write_error) {
++write_error_count_;
++trailing_write_error_count_;
+ TRACE_EVENT_INSTANT0("audio", "AudioInputSyncWriter write error",
+ TRACE_EVENT_SCOPE_THREAD);
} else {
trailing_write_error_count_ = 0;
}
@@ -330,6 +334,9 @@ bool AudioInputSyncWriter::SignalDataWrittenAndUpdateCounters() {
const std::string error_message = "AISW: No room in socket buffer.";
LOG(WARNING) << error_message;
AddToNativeLog(error_message);
+ TRACE_EVENT_INSTANT0("audio",
+ "AudioInputSyncWriter: No room in socket buffer",
+ TRACE_EVENT_SCOPE_THREAD);
return false;
}
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 1a6a995c1d2..0f316eb27bd 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -18,11 +18,11 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
+#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_sync_reader.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/render_widget_host_impl.h"
#include "content/common/media/audio_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -289,23 +289,15 @@ void AudioRendererHost::AudioEntry::OnCreated() {
}
void AudioRendererHost::AudioEntry::OnPlaying() {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
- host_,
- stream_id_,
- true));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::StreamStateChanged,
+ host_, stream_id_, true));
}
void AudioRendererHost::AudioEntry::OnPaused() {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
- host_,
- stream_id_,
- false));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::StreamStateChanged,
+ host_, stream_id_, false));
}
void AudioRendererHost::AudioEntry::OnError() {
@@ -363,19 +355,13 @@ void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) {
}
}
-void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
- bool is_playing) {
+void AudioRendererHost::StreamStateChanged(int stream_id, bool is_playing) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* const entry = LookupById(stream_id);
if (!entry)
return;
- Send(new AudioMsg_NotifyStreamStateChanged(
- stream_id,
- is_playing ? media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING
- : media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED));
-
if (is_playing) {
AudioStreamMonitor::StartMonitoringStream(
render_process_id_,
@@ -605,8 +591,7 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
}
void AudioRendererHost::SendErrorMessage(int stream_id) {
- Send(new AudioMsg_NotifyStreamStateChanged(
- stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR));
+ Send(new AudioMsg_NotifyStreamError(stream_id));
}
void AudioRendererHost::OnCloseStream(int stream_id) {
@@ -719,29 +704,19 @@ void AudioRendererHost::CheckOutputDeviceAccess(
}
if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
- AccessChecked(nullptr, device_id, security_origin, stream_id,
- auth_start_time, true);
+ AccessChecked(device_id, security_origin, stream_id, auth_start_time, true);
} else {
- // Check that MediaStream device permissions have been granted,
- // hence the use of a MediaStreamUIProxy.
- std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
-
- // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT
- // because MediaStreamUIProxy::CheckAccess does not currently support
- // MEDIA_DEVICE_AUDIO_OUTPUT.
- // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes
- // available. http://crbug.com/498675
- ui_proxy->CheckAccess(
- security_origin, MEDIA_DEVICE_AUDIO_CAPTURE, render_process_id_,
- render_frame_id,
- base::Bind(&AudioRendererHost::AccessChecked, this,
- base::Passed(&ui_proxy), device_id, security_origin,
- stream_id, auth_start_time));
+ // Check that device permissions have been granted for nondefault devices.
+ MediaDevicesPermissionChecker permission_checker;
+ permission_checker.CheckPermission(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id_, render_frame_id,
+ security_origin,
+ base::Bind(&AudioRendererHost::AccessChecked, this, device_id,
+ security_origin, stream_id, auth_start_time));
}
}
void AudioRendererHost::AccessChecked(
- std::unique_ptr<MediaStreamUIProxy> ui_proxy,
const std::string& device_id,
const url::Origin& security_origin,
int stream_id,
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
index 5643bed60de..63d4fe7a824 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
@@ -24,16 +24,16 @@
// | < NotifyStreamCreated |
// | |
// | PlayStream > |
-// | < NotifyStreamStateChanged | kAudioStreamPlaying
// | |
// | PauseStream > |
-// | < NotifyStreamStateChanged | kAudioStreamPaused
// | |
// | PlayStream > |
-// | < NotifyStreamStateChanged | kAudioStreamPlaying
// | ... |
// | CloseStream > |
// v v
+// If there is an error at any point, a NotifyStreamError will
+// be sent. Otherwise, the renderer can assume that the actual state
+// of the output stream is consistent with the control signals it sends.
// A SyncSocket pair is used to signal buffer readiness between processes.
@@ -76,8 +76,6 @@ namespace content {
class AudioMirroringManager;
class MediaInternals;
class MediaStreamManager;
-class MediaStreamUIProxy;
-class ResourceContext;
class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
public:
@@ -177,8 +175,9 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
// validated. When |is_valid| is false, this calls ReportErrorAndClose().
void DidValidateRenderFrame(int stream_id, bool is_valid);
- // Send playing/paused status to the renderer.
- void DoNotifyStreamStateChanged(int stream_id, bool is_playing);
+ // Updates status of stream for AudioStreamMonitor and updates
+ // the number of playing streams.
+ void StreamStateChanged(int stream_id, bool is_playing);
RenderProcessHost::AudioOutputControllerList DoGetOutputControllers() const;
@@ -208,8 +207,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
base::TimeTicks auth_start_time);
// Proceed with device authorization after checking permissions.
- void AccessChecked(std::unique_ptr<MediaStreamUIProxy> ui_proxy,
- const std::string& device_id,
+ void AccessChecked(const std::string& device_id,
const url::Origin& security_origin,
int stream_id,
base::TimeTicks auth_start_time,
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 5267e72eac2..1fe9f76f8b2 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
@@ -102,8 +102,6 @@ class MockAudioRendererHost : public AudioRendererHost {
const media::AudioParameters& output_params,
const std::string& matched_device_id));
MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
- MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
- MOCK_METHOD1(OnStreamPaused, void(int stream_id));
MOCK_METHOD1(OnStreamError, void(int stream_id));
private:
@@ -129,8 +127,7 @@ class MockAudioRendererHost : public AudioRendererHost {
OnNotifyDeviceAuthorized)
IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
OnNotifyStreamCreated)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
- OnNotifyStreamStateChanged)
+ IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamError, OnNotifyStreamError)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
@@ -168,23 +165,7 @@ class MockAudioRendererHost : public AudioRendererHost {
OnStreamCreated(stream_id, length);
}
- void OnNotifyStreamStateChanged(int stream_id,
- media::AudioOutputIPCDelegateState state) {
- switch (state) {
- case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING:
- OnStreamPlaying(stream_id);
- break;
- case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED:
- OnStreamPaused(stream_id);
- break;
- case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR:
- OnStreamError(stream_id);
- break;
- default:
- FAIL() << "Unknown stream state";
- break;
- }
- }
+ void OnNotifyStreamError(int stream_id) { OnStreamError(stream_id); }
std::unique_ptr<base::SharedMemory> shared_memory_;
std::unique_ptr<base::SyncSocket> sync_socket_;
@@ -321,13 +302,11 @@ class AudioRendererHostTest : public testing::Test {
}
void Play() {
- EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
host_->OnPlayStream(kStreamId);
SyncWithAudioThread();
}
void Pause() {
- EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId));
host_->OnPauseStream(kStreamId);
SyncWithAudioThread();
}
diff --git a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.cc b/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.cc
deleted file mode 100644
index 18f15aea2e4..00000000000
--- a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/gpu_memory_buffer_handle.h"
-
-#include "content/browser/renderer_host/media/gpu_memory_buffer_tracker.h"
-
-namespace content {
-
-GpuMemoryBufferBufferHandle::GpuMemoryBufferBufferHandle(
- GpuMemoryBufferTracker* tracker)
- : tracker_(tracker) {}
-GpuMemoryBufferBufferHandle::~GpuMemoryBufferBufferHandle() = default;
-
-gfx::Size GpuMemoryBufferBufferHandle::dimensions() const {
- return tracker_->dimensions();
-}
-
-size_t GpuMemoryBufferBufferHandle::mapped_size() const {
- return tracker_->dimensions().GetArea();
-}
-
-void* GpuMemoryBufferBufferHandle::data(int plane) {
- DCHECK_GE(plane, 0);
- DCHECK_LT(plane, static_cast<int>(tracker_->gpu_memory_buffers_.size()));
- DCHECK(tracker_->gpu_memory_buffers_[plane]);
- return tracker_->gpu_memory_buffers_[plane]->memory(0);
-}
-
-ClientBuffer GpuMemoryBufferBufferHandle::AsClientBuffer(int plane) {
- DCHECK_GE(plane, 0);
- DCHECK_LT(plane, static_cast<int>(tracker_->gpu_memory_buffers_.size()));
- return tracker_->gpu_memory_buffers_[plane]->AsClientBuffer();
-}
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-base::FileDescriptor GpuMemoryBufferBufferHandle::AsPlatformFile() {
- NOTREACHED();
- return base::FileDescriptor();
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.h b/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.h
deleted file mode 100644
index 4dd61a2297a..00000000000
--- a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_handle.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_HANDLE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_HANDLE_H_
-
-#include "media/capture/video/video_capture_buffer_handle.h"
-
-namespace content {
-
-class GpuMemoryBufferTracker;
-
-// A simple proxy that implements the BufferHandle interface, providing
-// accessors to GpuMemoryBufferTracker's memory and properties.
-class GpuMemoryBufferBufferHandle : public media::VideoCaptureBufferHandle {
- public:
- // |tracker| must outlive GpuMemoryBufferBufferHandle. This is ensured since
- // a tracker is pinned until ownership of this GpuMemoryBufferBufferHandle
- // is returned to VideoCaptureBufferPool.
- explicit GpuMemoryBufferBufferHandle(GpuMemoryBufferTracker* tracker);
- ~GpuMemoryBufferBufferHandle() override;
-
- gfx::Size dimensions() const override;
- size_t mapped_size() const override;
- void* data(int plane) override;
- ClientBuffer AsClientBuffer(int plane) override;
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
- base::FileDescriptor AsPlatformFile() override;
-#endif
-
- private:
- GpuMemoryBufferTracker* const tracker_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_HANDLE_H_
diff --git a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.cc b/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.cc
deleted file mode 100644
index a19461f75f0..00000000000
--- a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/gpu_memory_buffer_tracker.h"
-
-#include "base/memory/ptr_util.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
-#include "content/browser/renderer_host/media/gpu_memory_buffer_handle.h"
-#include "content/public/browser/browser_thread.h"
-#include "media/base/video_frame.h"
-
-namespace content {
-
-GpuMemoryBufferTracker::GpuMemoryBufferTracker()
- : VideoCaptureBufferTracker() {}
-
-GpuMemoryBufferTracker::~GpuMemoryBufferTracker() {
- for (const auto& gmb : gpu_memory_buffers_)
- gmb->Unmap();
-}
-
-bool GpuMemoryBufferTracker::Init(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage_type,
- base::Lock* lock) {
- DVLOG(2) << "allocating GMB for " << dimensions.ToString();
- // BrowserGpuMemoryBufferManager::current() may not be accessed on IO
- // Thread.
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(BrowserGpuMemoryBufferManager::current());
- // This class is only expected to be called with I420 buffer requests at
- // this point.
- DCHECK_EQ(format, media::PIXEL_FORMAT_I420);
- set_dimensions(dimensions);
- set_max_pixel_count(dimensions.GetArea());
- set_pixel_format(format);
- set_storage_type(storage_type);
- // |dimensions| can be 0x0 for trackers that do not require memory backing.
- if (dimensions.GetArea() == 0u)
- return true;
-
- base::AutoUnlock auto_unlock(*lock);
- const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format());
- for (size_t i = 0; i < num_planes; ++i) {
- const gfx::Size& size =
- media::VideoFrame::PlaneSize(pixel_format(), i, dimensions);
- gpu_memory_buffers_.push_back(
- BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer(
- size, gfx::BufferFormat::R_8,
- gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
- gpu::kNullSurfaceHandle));
-
- DLOG_IF(ERROR, !gpu_memory_buffers_[i]) << "Allocating GpuMemoryBuffer";
- if (!gpu_memory_buffers_[i] || !gpu_memory_buffers_[i]->Map())
- return false;
- }
- return true;
-}
-
-std::unique_ptr<media::VideoCaptureBufferHandle>
-GpuMemoryBufferTracker::GetBufferHandle() {
- DCHECK_EQ(gpu_memory_buffers_.size(),
- media::VideoFrame::NumPlanes(pixel_format()));
- return base::MakeUnique<GpuMemoryBufferBufferHandle>(this);
-}
-
-bool GpuMemoryBufferTracker::ShareToProcess(
- base::ProcessHandle process_handle,
- base::SharedMemoryHandle* new_handle) {
- NOTREACHED();
- return false;
-}
-
-bool GpuMemoryBufferTracker::ShareToProcess2(
- int plane,
- base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) {
- DCHECK_LE(plane, static_cast<int>(gpu_memory_buffers_.size()));
-
- const auto& current_gmb_handle = gpu_memory_buffers_[plane]->GetHandle();
- switch (current_gmb_handle.type) {
- case gfx::EMPTY_BUFFER:
- NOTREACHED();
- return false;
- case gfx::SHARED_MEMORY_BUFFER: {
- DCHECK(base::SharedMemory::IsHandleValid(current_gmb_handle.handle));
- base::SharedMemory shared_memory(
- base::SharedMemory::DuplicateHandle(current_gmb_handle.handle),
- false);
- shared_memory.ShareToProcess(process_handle, &new_handle->handle);
- DCHECK(base::SharedMemory::IsHandleValid(new_handle->handle));
- new_handle->type = gfx::SHARED_MEMORY_BUFFER;
- return true;
- }
- case gfx::IO_SURFACE_BUFFER:
- case gfx::OZONE_NATIVE_PIXMAP:
- *new_handle = current_gmb_handle;
- return true;
- }
- NOTREACHED();
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.h b/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.h
deleted file mode 100644
index c3f13d16dc9..00000000000
--- a/chromium/content/browser/renderer_host/media/gpu_memory_buffer_tracker.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_TRACKER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_TRACKER_H_
-
-#include "media/capture/video/video_capture_buffer_tracker.h"
-
-namespace content {
-
-// Tracker specifics for GpuMemoryBuffer. Owns GpuMemoryBuffers and its
-// associated pixel dimensions.
-class GpuMemoryBufferTracker final : public media::VideoCaptureBufferTracker {
- public:
- GpuMemoryBufferTracker();
- ~GpuMemoryBufferTracker() override;
-
- bool Init(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage_type,
- base::Lock* lock) override;
-
- std::unique_ptr<media::VideoCaptureBufferHandle> GetBufferHandle() override;
-
- bool ShareToProcess(base::ProcessHandle process_handle,
- base::SharedMemoryHandle* new_handle) override;
-
- bool ShareToProcess2(int plane,
- base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) override;
-
- private:
- friend class GpuMemoryBufferBufferHandle;
-
- // Owned references to GpuMemoryBuffers.
- std::vector<std::unique_ptr<gfx::GpuMemoryBuffer>> gpu_memory_buffers_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_GPU_MEMORY_BUFFER_TRACKER_H_
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
new file mode 100644
index 00000000000..5cbc36f1fe5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -0,0 +1,296 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/media_devices_dispatcher_host.h"
+
+#include <stddef.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/common/media/media_devices.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/media_device_id.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/media_stream_request.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+MediaDeviceInfo TranslateDeviceInfo(bool has_permission,
+ const std::string& device_id_salt,
+ const std::string& group_id_salt,
+ const url::Origin& security_origin,
+ const MediaDeviceInfo& device_info) {
+ return MediaDeviceInfo(
+ GetHMACForMediaDeviceID(device_id_salt, security_origin,
+ device_info.device_id),
+ has_permission ? device_info.label : std::string(),
+ device_info.group_id.empty()
+ ? std::string()
+ : GetHMACForMediaDeviceID(group_id_salt, security_origin,
+ device_info.group_id));
+}
+
+MediaDeviceInfoArray TranslateMediaDeviceInfoArray(
+ bool has_permission,
+ const std::string& device_id_salt,
+ const std::string& group_id_salt,
+ const url::Origin& security_origin,
+ const MediaDeviceInfoArray& input) {
+ MediaDeviceInfoArray result;
+ for (const auto& device_info : input) {
+ result.push_back(TranslateDeviceInfo(has_permission, device_id_salt,
+ group_id_salt, security_origin,
+ device_info));
+ }
+ return result;
+}
+
+} // namespace
+
+struct MediaDevicesDispatcherHost::SubscriptionInfo {
+ uint32_t subscription_id;
+ url::Origin security_origin;
+};
+
+// static
+void MediaDevicesDispatcherHost::Create(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id_salt,
+ MediaStreamManager* media_stream_manager,
+ ::mojom::MediaDevicesDispatcherHostRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ mojo::MakeStrongBinding(base::MakeUnique<MediaDevicesDispatcherHost>(
+ render_process_id, render_frame_id,
+ device_id_salt, media_stream_manager),
+ std::move(request));
+}
+
+MediaDevicesDispatcherHost::MediaDevicesDispatcherHost(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id_salt,
+ MediaStreamManager* media_stream_manager)
+ : render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id),
+ device_id_salt_(device_id_salt),
+ group_id_salt_(ResourceContext::CreateRandomMediaDeviceIDSalt()),
+ media_stream_manager_(media_stream_manager),
+ permission_checker_(base::MakeUnique<MediaDevicesPermissionChecker>()),
+ weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+MediaDevicesDispatcherHost::~MediaDevicesDispatcherHost() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ if (!device_change_subscriptions_[i].empty()) {
+ media_stream_manager_->media_devices_manager()
+ ->UnsubscribeDeviceChangeNotifications(
+ static_cast<MediaDeviceType>(i), this);
+ }
+ }
+}
+
+void MediaDevicesDispatcherHost::EnumerateDevices(
+ bool request_audio_input,
+ bool request_video_input,
+ bool request_audio_output,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!request_audio_input && !request_video_input && !request_audio_output) {
+ bad_message::ReceivedBadMessage(
+ render_process_id_, bad_message::MDDH_INVALID_DEVICE_TYPE_REQUEST);
+ return;
+ }
+
+ // Ignore requests from unique origins, but do not crash the renderer.
+ if (security_origin.unique())
+ return;
+
+ if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
+ security_origin)) {
+ bad_message::ReceivedBadMessage(render_process_id_,
+ bad_message::MDDH_UNAUTHORIZED_ORIGIN);
+ return;
+ }
+
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = request_audio_input;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = request_video_input;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = request_audio_output;
+
+ permission_checker_->CheckPermissions(
+ devices_to_enumerate, render_process_id_, render_frame_id_,
+ security_origin,
+ base::Bind(&MediaDevicesDispatcherHost::DoEnumerateDevices,
+ weak_factory_.GetWeakPtr(), devices_to_enumerate,
+ security_origin, client_callback));
+}
+
+void MediaDevicesDispatcherHost::SubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ uint32_t subscription_id,
+ const url::Origin& security_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(IsValidMediaDeviceType(type));
+ if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
+ security_origin)) {
+ bad_message::ReceivedBadMessage(render_process_id_,
+ bad_message::MDDH_UNAUTHORIZED_ORIGIN);
+ return;
+ }
+
+ auto it = std::find_if(device_change_subscriptions_[type].begin(),
+ device_change_subscriptions_[type].end(),
+ [subscription_id](const SubscriptionInfo& info) {
+ return info.subscription_id == subscription_id;
+ });
+
+ if (it != device_change_subscriptions_[type].end()) {
+ bad_message::ReceivedBadMessage(
+ render_process_id_, bad_message::MDDH_INVALID_SUBSCRIPTION_REQUEST);
+ return;
+ }
+
+ if (device_change_subscriptions_[type].empty()) {
+ media_stream_manager_->media_devices_manager()
+ ->SubscribeDeviceChangeNotifications(type, this);
+ }
+
+ device_change_subscriptions_[type].push_back(
+ SubscriptionInfo{subscription_id, security_origin});
+}
+
+void MediaDevicesDispatcherHost::UnsubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ uint32_t subscription_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(IsValidMediaDeviceType(type));
+ auto it = std::find_if(device_change_subscriptions_[type].begin(),
+ device_change_subscriptions_[type].end(),
+ [subscription_id](const SubscriptionInfo& info) {
+ return info.subscription_id == subscription_id;
+ });
+
+ if (it == device_change_subscriptions_[type].end()) {
+ bad_message::ReceivedBadMessage(
+ render_process_id_, bad_message::MDDH_INVALID_UNSUBSCRIPTION_REQUEST);
+ return;
+ }
+
+ device_change_subscriptions_[type].erase(it);
+ if (device_change_subscriptions_[type].empty()) {
+ media_stream_manager_->media_devices_manager()
+ ->UnsubscribeDeviceChangeNotifications(type, this);
+ }
+}
+
+void MediaDevicesDispatcherHost::OnDevicesChanged(
+ MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(IsValidMediaDeviceType(type));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&MediaDevicesDispatcherHost::NotifyDeviceChangeOnUIThread,
+ weak_factory_.GetWeakPtr(), device_change_subscriptions_[type],
+ type, device_infos));
+}
+
+void MediaDevicesDispatcherHost::NotifyDeviceChangeOnUIThread(
+ const std::vector<SubscriptionInfo>& subscriptions,
+ MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(IsValidMediaDeviceType(type));
+
+ ::mojom::MediaDevicesListenerPtr media_devices_listener;
+ if (device_change_listener_) {
+ media_devices_listener = std::move(device_change_listener_);
+ } else {
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+ if (!render_frame_host)
+ return;
+
+ render_frame_host->GetRemoteInterfaces()->GetInterface(
+ mojo::GetProxy(&media_devices_listener));
+ if (!media_devices_listener)
+ return;
+ }
+
+ for (const auto& subscription : subscriptions) {
+ bool has_permission = permission_checker_->CheckPermissionOnUIThread(
+ type, render_process_id_, render_frame_id_,
+ subscription.security_origin);
+ media_devices_listener->OnDevicesChanged(
+ type, subscription.subscription_id,
+ TranslateMediaDeviceInfoArray(
+ has_permission, device_id_salt_, group_id_salt_,
+ subscription.security_origin, device_infos));
+ }
+}
+
+void MediaDevicesDispatcherHost::SetPermissionChecker(
+ std::unique_ptr<MediaDevicesPermissionChecker> permission_checker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(permission_checker);
+ permission_checker_ = std::move(permission_checker);
+}
+
+void MediaDevicesDispatcherHost::SetDeviceChangeListenerForTesting(
+ ::mojom::MediaDevicesListenerPtr listener) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ device_change_listener_ = std::move(listener);
+}
+
+void MediaDevicesDispatcherHost::DoEnumerateDevices(
+ const MediaDevicesManager::BoolDeviceTypes& requested_types,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback,
+ const MediaDevicesManager::BoolDeviceTypes& has_permissions) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ media_stream_manager_->media_devices_manager()->EnumerateDevices(
+ requested_types,
+ base::Bind(&MediaDevicesDispatcherHost::DevicesEnumerated,
+ weak_factory_.GetWeakPtr(), requested_types, security_origin,
+ client_callback, has_permissions));
+}
+
+void MediaDevicesDispatcherHost::DevicesEnumerated(
+ const MediaDevicesManager::BoolDeviceTypes& requested_types,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback,
+ const MediaDevicesManager::BoolDeviceTypes& has_permissions,
+ const MediaDeviceEnumeration& enumeration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<std::vector<MediaDeviceInfo>> result(NUM_MEDIA_DEVICE_TYPES);
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ if (!requested_types[i])
+ continue;
+
+ for (const auto& device_info : enumeration[i]) {
+ result[i].push_back(TranslateDeviceInfo(has_permissions[i],
+ device_id_salt_, group_id_salt_,
+ security_origin, device_info));
+ }
+ }
+ client_callback.Run(result);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h
new file mode 100644
index 00000000000..12ca0240e42
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -0,0 +1,110 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_DISPATCHER_HOST_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "content/browser/media/media_devices_permission_checker.h"
+#include "content/browser/renderer_host/media/media_devices_manager.h"
+#include "content/common/content_export.h"
+#include "content/common/media/media_devices.mojom.h"
+
+using ::mojom::MediaDeviceType;
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+class MediaStreamManager;
+
+class CONTENT_EXPORT MediaDevicesDispatcherHost
+ : public ::mojom::MediaDevicesDispatcherHost,
+ public MediaDeviceChangeSubscriber {
+ public:
+ MediaDevicesDispatcherHost(int render_process_id,
+ int render_frame_id,
+ const std::string& device_id_salt,
+ MediaStreamManager* media_stream_manager);
+ ~MediaDevicesDispatcherHost() override;
+
+ static void Create(int render_process_id,
+ int render_frame_id,
+ const std::string& device_id_salt,
+ MediaStreamManager* media_stream_manager,
+ ::mojom::MediaDevicesDispatcherHostRequest request);
+
+ // ::mojom::MediaDevicesDispatcherHost implementation.
+ void EnumerateDevices(
+ bool request_audio_input,
+ bool request_video_input,
+ bool request_audio_output,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback) override;
+ void SubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ uint32_t subscription_id,
+ const url::Origin& security_origin) override;
+ void UnsubscribeDeviceChangeNotifications(MediaDeviceType type,
+ uint32_t subscription_id) override;
+
+ // MediaDeviceChangeSubscriber implementation.
+ void OnDevicesChanged(MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos) override;
+
+ void SetPermissionChecker(
+ std::unique_ptr<MediaDevicesPermissionChecker> permission_checker);
+
+ void SetDeviceChangeListenerForTesting(
+ ::mojom::MediaDevicesListenerPtr listener);
+
+ private:
+ void DoEnumerateDevices(
+ const MediaDevicesManager::BoolDeviceTypes& requested_types,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback,
+ const MediaDevicesManager::BoolDeviceTypes& permissions);
+
+ void DevicesEnumerated(
+ const MediaDevicesManager::BoolDeviceTypes& requested_types,
+ const url::Origin& security_origin,
+ const EnumerateDevicesCallback& client_callback,
+ const MediaDevicesManager::BoolDeviceTypes& has_permissions,
+ const MediaDeviceEnumeration& enumeration);
+
+ struct SubscriptionInfo;
+ void NotifyDeviceChangeOnUIThread(
+ const std::vector<SubscriptionInfo>& subscriptions,
+ MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos);
+
+ // The following const fields can be accessed on any thread.
+ const int render_process_id_;
+ const int render_frame_id_;
+ const std::string device_id_salt_;
+ const std::string group_id_salt_;
+
+ // The following fields can only be accessed on the IO thread.
+ MediaStreamManager* media_stream_manager_;
+ std::unique_ptr<MediaDevicesPermissionChecker> permission_checker_;
+ std::vector<SubscriptionInfo>
+ device_change_subscriptions_[NUM_MEDIA_DEVICE_TYPES];
+
+ // This field can only be accessed on the UI thread.
+ ::mojom::MediaDevicesListenerPtr device_change_listener_;
+
+ base::WeakPtrFactory<MediaDevicesDispatcherHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaDevicesDispatcherHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_DISPATCHER_HOST_H_
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
new file mode 100644
index 00000000000..8e1c47943d4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -0,0 +1,331 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/media_devices_dispatcher_host.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <queue>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.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"
+#include "content/public/browser/media_device_id.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/base/media_switches.h"
+#include "media/capture/video/fake_video_capture_device_factory.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
+
+using testing::_;
+using testing::SaveArg;
+
+namespace content {
+
+namespace {
+
+const int kProcessId = 5;
+const int kRenderId = 6;
+
+void PhysicalDevicesEnumerated(base::Closure quit_closure,
+ MediaDeviceEnumeration* out,
+ const MediaDeviceEnumeration& enumeration) {
+ *out = enumeration;
+ quit_closure.Run();
+}
+
+class MockMediaDevicesListener : public ::mojom::MediaDevicesListener {
+ public:
+ MockMediaDevicesListener() : binding_(this) {}
+
+ MOCK_METHOD3(OnDevicesChanged,
+ void(MediaDeviceType, uint32_t, const MediaDeviceInfoArray&));
+
+ ::mojom::MediaDevicesListenerPtr CreateInterfacePtrAndBind() {
+ return binding_.CreateInterfacePtrAndBind();
+ }
+
+ private:
+ mojo::Binding<::mojom::MediaDevicesListener> binding_;
+};
+
+} // namespace
+
+class MediaDevicesDispatcherHostTest : public testing::Test {
+ public:
+ MediaDevicesDispatcherHostTest()
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ origin_(GURL("https://test.com")) {
+ // Make sure we use fake devices to avoid long delays.
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kUseFakeDeviceForMediaStream);
+ audio_manager_.reset(
+ new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get()));
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
+
+ MockResourceContext* mock_resource_context =
+ static_cast<MockResourceContext*>(
+ browser_context_.GetResourceContext());
+
+ host_ = base::MakeUnique<MediaDevicesDispatcherHost>(
+ kProcessId, kRenderId, mock_resource_context->GetMediaDeviceIDSalt(),
+ media_stream_manager_.get());
+ }
+
+ void SetUp() override {
+ base::RunLoop run_loop;
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
+ media_stream_manager_->media_devices_manager()->EnumerateDevices(
+ devices_to_enumerate,
+ base::Bind(&PhysicalDevicesEnumerated, run_loop.QuitClosure(),
+ &physical_devices_));
+ run_loop.Run();
+
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size(), 0u);
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_VIDEO_INPUT].size(), 0u);
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].size(), 0u);
+ }
+
+ MOCK_METHOD1(UniqueOriginCallback,
+ void(const std::vector<std::vector<MediaDeviceInfo>>&));
+ MOCK_METHOD1(ValidOriginCallback,
+ void(const std::vector<std::vector<MediaDeviceInfo>>&));
+
+ protected:
+ void DevicesEnumerated(
+ const base::Closure& closure,
+ const std::vector<std::vector<MediaDeviceInfo>>& devices) {
+ enumerated_devices_ = devices;
+ closure.Run();
+ }
+
+ void EnumerateDevicesAndWaitForResult(bool enumerate_audio_input,
+ bool enumerate_video_input,
+ bool enumerate_audio_output,
+ bool permission_override_value = true) {
+ host_->SetPermissionChecker(base::MakeUnique<MediaDevicesPermissionChecker>(
+ permission_override_value));
+ base::RunLoop run_loop;
+ host_->EnumerateDevices(
+ enumerate_audio_input, enumerate_video_input, enumerate_audio_output,
+ origin_, base::Bind(&MediaDevicesDispatcherHostTest::DevicesEnumerated,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+
+ ASSERT_FALSE(enumerated_devices_.empty());
+ if (enumerate_audio_input)
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_AUDIO_INPUT].empty());
+ if (enumerate_video_input)
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_VIDEO_INPUT].empty());
+ if (enumerate_audio_output)
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].empty());
+
+ EXPECT_FALSE(DoesContainRawIds(enumerated_devices_));
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(enumerated_devices_, origin_));
+ }
+
+ bool DoesContainRawIds(
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration) {
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ for (const auto& device_info : enumeration[i]) {
+ for (const auto& raw_device_info : physical_devices_[i]) {
+ // Skip default and communications audio devices, whose IDs are not
+ // translated.
+ if (device_info.device_id ==
+ media::AudioDeviceDescription::kDefaultDeviceId ||
+ device_info.device_id ==
+ media::AudioDeviceDescription::kCommunicationsDeviceId) {
+ continue;
+ }
+ if (device_info.device_id == raw_device_info.device_id)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool DoesEveryDeviceMapToRawId(
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration,
+ const url::Origin& origin) {
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ for (const auto& device_info : enumeration[i]) {
+ bool found_match = false;
+ for (const auto& raw_device_info : physical_devices_[i]) {
+ if (DoesMediaDeviceIDMatchHMAC(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin, device_info.device_id, raw_device_info.device_id)) {
+ EXPECT_FALSE(found_match);
+ found_match = true;
+ }
+ }
+ if (!found_match)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Returns true if all devices have labels, false otherwise.
+ bool DoesContainLabels(const MediaDeviceInfoArray& device_infos) {
+ for (const auto& device_info : device_infos) {
+ if (device_info.label.empty())
+ return false;
+ }
+ return true;
+ }
+
+ // Returns true if all devices have labels, false otherwise.
+ bool DoesContainLabels(const std::vector<MediaDeviceInfoArray>& enumeration) {
+ for (const auto& device_infos : enumeration) {
+ if (!DoesContainLabels(device_infos))
+ return false;
+ }
+ return true;
+ }
+
+ // Returns true if no devices have labels, false otherwise.
+ bool DoesNotContainLabels(const MediaDeviceInfoArray& device_infos) {
+ for (const auto& device_info : device_infos) {
+ if (!device_info.label.empty())
+ return false;
+ }
+ return true;
+ }
+
+ // Returns true if no devices have labels, false otherwise.
+ bool DoesNotContainLabels(
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration) {
+ for (const auto& device_infos : enumeration) {
+ if (!DoesNotContainLabels(device_infos))
+ return false;
+ }
+ return true;
+ }
+
+ void SubscribeAndWaitForResult(bool has_permission) {
+ host_->SetPermissionChecker(
+ base::MakeUnique<MediaDevicesPermissionChecker>(has_permission));
+ uint32_t subscription_id = 0u;
+ url::Origin origin(GURL("http://localhost"));
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ MediaDeviceType type = static_cast<MediaDeviceType>(i);
+ host_->SubscribeDeviceChangeNotifications(type, subscription_id, origin);
+ MockMediaDevicesListener device_change_listener;
+ host_->SetDeviceChangeListenerForTesting(
+ device_change_listener.CreateInterfacePtrAndBind());
+ MediaDeviceInfoArray changed_devices;
+ EXPECT_CALL(device_change_listener,
+ OnDevicesChanged(type, subscription_id, testing::_))
+ .WillRepeatedly(SaveArg<2>(&changed_devices));
+
+ // Simulate device-change notification
+ MediaDeviceInfoArray updated_devices = {
+ {"fake_device_id", "fake_label", "fake_group"}};
+ host_->OnDevicesChanged(type, updated_devices);
+ base::RunLoop().RunUntilIdle();
+ host_->UnsubscribeDeviceChangeNotifications(type, subscription_id);
+
+ if (has_permission)
+ EXPECT_TRUE(DoesContainLabels(changed_devices));
+ else
+ EXPECT_TRUE(DoesNotContainLabels(changed_devices));
+ }
+ }
+
+ std::unique_ptr<MediaDevicesDispatcherHost> host_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
+ content::TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<media::AudioManager, media::AudioManagerDeleter>
+ audio_manager_;
+ content::TestBrowserContext browser_context_;
+ MediaDeviceEnumeration physical_devices_;
+ url::Origin origin_;
+
+ std::vector<MediaDeviceInfoArray> enumerated_devices_;
+};
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioInputDevices) {
+ EnumerateDevicesAndWaitForResult(true, false, false);
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateVideoInputDevices) {
+ EnumerateDevicesAndWaitForResult(false, true, false);
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioOutputDevices) {
+ EnumerateDevicesAndWaitForResult(false, false, true);
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAllDevices) {
+ EnumerateDevicesAndWaitForResult(true, true, true);
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioInputDevicesNoAccess) {
+ EnumerateDevicesAndWaitForResult(true, false, false, false);
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateVideoInputDevicesNoAccess) {
+ EnumerateDevicesAndWaitForResult(false, true, false, false);
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioOutputDevicesNoAccess) {
+ EnumerateDevicesAndWaitForResult(false, false, true, false);
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAllDevicesNoAccess) {
+ EnumerateDevicesAndWaitForResult(true, true, true, false);
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_));
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, SubscribeDeviceChange) {
+ SubscribeAndWaitForResult(true);
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, SubscribeDeviceChangeNoAccess) {
+ SubscribeAndWaitForResult(false);
+}
+
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAllDevicesUniqueOrigin) {
+ EXPECT_CALL(*this, UniqueOriginCallback(testing::_)).Times(0);
+ host_->EnumerateDevices(
+ true, true, true, url::Origin(),
+ base::Bind(&MediaDevicesDispatcherHostTest::UniqueOriginCallback,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+
+ // Verify that the callback for a valid origin does get called.
+ EXPECT_CALL(*this, ValidOriginCallback(testing::_));
+ host_->EnumerateDevices(
+ true, true, true, url::Origin(GURL("http://localhost")),
+ base::Bind(&MediaDevicesDispatcherHostTest::ValidOriginCallback,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+}
+
+}; // namespace content
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 de50a1f8206..8f85f5ced95 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -209,6 +209,27 @@ void MediaDevicesManager::EnumerateDevices(
ProcessRequests();
}
+void MediaDevicesManager::SubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ MediaDeviceChangeSubscriber* subscriber) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto it = std::find(device_change_subscribers_[type].begin(),
+ device_change_subscribers_[type].end(), subscriber);
+ if (it == device_change_subscribers_[type].end())
+ device_change_subscribers_[type].push_back(subscriber);
+}
+
+void MediaDevicesManager::UnsubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ MediaDeviceChangeSubscriber* subscriber) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto it = std::find(device_change_subscribers_[type].begin(),
+ device_change_subscribers_[type].end(), subscriber);
+ if (it != device_change_subscribers_[type].end())
+ device_change_subscribers_[type].erase(it);
+}
+
void MediaDevicesManager::SetCachePolicy(MediaDeviceType type,
CachePolicy policy) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -504,18 +525,9 @@ void MediaDevicesManager::NotifyDeviceChangeSubscribers(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(IsValidMediaDeviceType(type));
- // TODO(guidou): Use device types instead of stream types, and remove the
- // call to MediaStreamManager once handling of device-change subscriptions
- // is removed from MediaStreamManager. See http://crbug.com/334244.
- // |permission_type| is used by MediaStreamManager to decide which permission
- // to check before forwarding the event to the renderer process. Since there
- // is no separate permission for audio output devices yet, use
- // MEDIA_DEVICE_AUDIO_CAPTURE for both audio input and output.
- MediaStreamType permission_type = type == MEDIA_DEVICE_TYPE_VIDEO_INPUT
- ? MEDIA_DEVICE_VIDEO_CAPTURE
- : MEDIA_DEVICE_AUDIO_CAPTURE;
- if (media_stream_manager_)
- media_stream_manager_->NotifyDeviceChangeSubscribers(permission_type);
+ for (const auto& subscriber : device_change_subscribers_[type]) {
+ subscriber->OnDevicesChanged(type, snapshot);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager.h b/chromium/content/browser/renderer_host/media/media_devices_manager.h
index 55acd9ac8d0..63b0040959f 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.h
@@ -16,10 +16,6 @@
#include "content/common/media/media_devices.h"
#include "media/capture/video/video_capture_device_descriptor.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace media {
class AudioManager;
}
@@ -33,6 +29,18 @@ class VideoCaptureManager;
using MediaDeviceEnumeration =
std::array<MediaDeviceInfoArray, NUM_MEDIA_DEVICE_TYPES>;
+// MediaDeviceChangeSubscriber is an interface to be implemented by classes
+// that can register with MediaDevicesManager to get notifications about changes
+// in the set of media devices.
+class CONTENT_EXPORT MediaDeviceChangeSubscriber {
+ public:
+ // This function is invoked to notify about changes in the set of media
+ // devices of type |type|. |device_infos| contains the updated list of
+ // devices of type |type|.
+ virtual void OnDevicesChanged(MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos) = 0;
+};
+
// MediaDevicesManager is responsible for doing media-device enumerations.
// In addition it implements caching for enumeration results and device
// monitoring in order to keep caches consistent.
@@ -67,6 +75,22 @@ class CONTENT_EXPORT MediaDevicesManager
void EnumerateDevices(const BoolDeviceTypes& requested_types,
const EnumerationCallback& callback);
+ // Subscribes |subscriber| to receive device-change notifications for devices
+ // of type |type|. If |subscriber| is already subscribed, this function has
+ // no side effects. MediaDevicesManager does not own |subscriber|. It is the
+ // responsibility of the caller to ensure that all registered subscribers
+ // remain valid while the they are subscribed.
+ void SubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ MediaDeviceChangeSubscriber* subscriber);
+
+ // Unubscribes |subscriber| from device-change notifications for the devices
+ // of type |type|. If |subscriber| is not subscribed, this function has no
+ // side effects.
+ void UnsubscribeDeviceChangeNotifications(
+ MediaDeviceType type,
+ MediaDeviceChangeSubscriber* subscriber);
+
// Tries to start device monitoring. If successful, enables caching of
// enumeration results for the device types supported by the monitor.
void StartMonitoring();
@@ -149,6 +173,9 @@ class CONTENT_EXPORT MediaDevicesManager
MediaDeviceEnumeration current_snapshot_;
bool monitoring_started_;
+ std::vector<MediaDeviceChangeSubscriber*>
+ device_change_subscribers_[NUM_MEDIA_DEVICE_TYPES];
+
base::WeakPtrFactory<MediaDevicesManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaDevicesManager);
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
index 23c3701bc02..cdbac6481a7 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
@@ -114,6 +114,12 @@ class MockVideoCaptureDeviceFactory
}
};
+class MockMediaDeviceChangeSubscriber : public MediaDeviceChangeSubscriber {
+ public:
+ MOCK_METHOD2(OnDevicesChanged,
+ void(MediaDeviceType, const MediaDeviceInfoArray&));
+};
+
} // namespace
class MediaDevicesManagerTest : public ::testing::Test {
@@ -438,4 +444,123 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAllWithDeviceChanges) {
}
}
+TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
+ EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(3);
+ EXPECT_CALL(*video_capture_device_factory_, MockGetDeviceDescriptors())
+ .Times(3);
+ EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_)).Times(3);
+
+ size_t num_audio_input_devices = 5;
+ size_t num_video_input_devices = 4;
+ size_t num_audio_output_devices = 3;
+ audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
+ video_capture_device_factory_->set_number_of_devices(num_video_input_devices);
+ audio_manager_->SetNumAudioOutputDevices(num_audio_output_devices);
+
+ // Run an enumeration to make sure |media_devices_manager_| has the new
+ // configuration.
+ EXPECT_CALL(*this, MockCallback(_));
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
+ base::RunLoop run_loop;
+ media_devices_manager_->EnumerateDevices(
+ devices_to_enumerate,
+ base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
+ run_loop.Run();
+
+ // Add device-change event subscribers.
+ MockMediaDeviceChangeSubscriber subscriber_audio_input;
+ MockMediaDeviceChangeSubscriber subscriber_video_input;
+ MockMediaDeviceChangeSubscriber subscriber_audio_output;
+ MockMediaDeviceChangeSubscriber subscriber_all;
+
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_audio_input);
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_video_input);
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_audio_output);
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_all);
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_all);
+ media_devices_manager_->SubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_all);
+
+ MediaDeviceInfoArray notification_audio_input;
+ MediaDeviceInfoArray notification_video_input;
+ MediaDeviceInfoArray notification_audio_output;
+ MediaDeviceInfoArray notification_all_audio_input;
+ MediaDeviceInfoArray notification_all_video_input;
+ MediaDeviceInfoArray notification_all_audio_output;
+ EXPECT_CALL(subscriber_audio_input,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&notification_audio_input));
+ EXPECT_CALL(subscriber_video_input,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&notification_video_input));
+ EXPECT_CALL(subscriber_audio_output,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&notification_audio_output));
+ EXPECT_CALL(subscriber_all,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
+ .Times(2)
+ .WillRepeatedly(SaveArg<1>(&notification_all_audio_input));
+ EXPECT_CALL(subscriber_all,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
+ .Times(2)
+ .WillRepeatedly(SaveArg<1>(&notification_all_video_input));
+ EXPECT_CALL(subscriber_all,
+ OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
+ .Times(2)
+ .WillRepeatedly(SaveArg<1>(&notification_all_audio_output));
+
+ // Simulate device changes.
+ num_audio_input_devices = 3;
+ num_video_input_devices = 2;
+ num_audio_output_devices = 4;
+ audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
+ video_capture_device_factory_->set_number_of_devices(num_video_input_devices);
+ audio_manager_->SetNumAudioOutputDevices(num_audio_output_devices);
+ media_devices_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
+ media_devices_manager_->OnDevicesChanged(
+ base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(num_audio_input_devices, notification_audio_input.size());
+ EXPECT_EQ(num_video_input_devices, notification_video_input.size());
+ EXPECT_EQ(num_audio_output_devices, notification_audio_output.size());
+ EXPECT_EQ(num_audio_input_devices, notification_all_audio_input.size());
+ EXPECT_EQ(num_video_input_devices, notification_all_video_input.size());
+ EXPECT_EQ(num_audio_output_devices, notification_all_audio_output.size());
+
+ media_devices_manager_->UnsubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_audio_input);
+ media_devices_manager_->UnsubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_video_input);
+ media_devices_manager_->UnsubscribeDeviceChangeNotifications(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_audio_output);
+
+ // Simulate further device changes. Only the objects still subscribed to the
+ // device-change events will receive notifications.
+ num_audio_input_devices = 2;
+ num_video_input_devices = 1;
+ num_audio_output_devices = 3;
+ audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
+ video_capture_device_factory_->set_number_of_devices(num_video_input_devices);
+ audio_manager_->SetNumAudioOutputDevices(num_audio_output_devices);
+ media_devices_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
+ media_devices_manager_->OnDevicesChanged(
+ base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(num_audio_input_devices, notification_all_audio_input.size());
+ EXPECT_EQ(num_video_input_devices, notification_all_video_input.size());
+ EXPECT_EQ(num_audio_output_devices, notification_all_audio_output.size());
+}
+
} // namespace content
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 ed0f30059cb..3a2e040afd6 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
@@ -6,30 +6,23 @@
#include <algorithm>
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "content/browser/bad_message.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/renderer_host/media/media_stream_ui_proxy.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 "url/gurl.h"
+#include "url/origin.h"
namespace content {
MediaStreamDispatcherHost::MediaStreamDispatcherHost(
int render_process_id,
const std::string& salt,
- MediaStreamManager* media_stream_manager,
- bool use_fake_ui)
+ MediaStreamManager* media_stream_manager)
: BrowserMessageFilter(MediaStreamMsgStart),
render_process_id_(render_process_id),
salt_(salt),
- media_stream_manager_(media_stream_manager),
- use_fake_ui_(use_fake_ui),
- weak_factory_(this) {}
+ media_stream_manager_(media_stream_manager) {}
void MediaStreamDispatcherHost::StreamGenerated(
int render_frame_id,
@@ -71,19 +64,6 @@ void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id,
Send(new MediaStreamMsg_DeviceStopped(render_frame_id, label, device));
}
-void MediaStreamDispatcherHost::DevicesEnumerated(
- int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated("
- << ", {page_request_id = " << page_request_id << "})";
-
- Send(new MediaStreamMsg_DevicesEnumerated(render_frame_id, page_request_id,
- devices));
-}
-
void MediaStreamDispatcherHost::DeviceOpened(
int render_frame_id,
int page_request_id,
@@ -97,22 +77,6 @@ void MediaStreamDispatcherHost::DeviceOpened(
render_frame_id, page_request_id, label, video_device));
}
-void MediaStreamDispatcherHost::DevicesChanged(MediaStreamType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::DevicesChanged("
- << "{type = " << type << "})";
- for (const auto& subscriber : device_change_subscribers_) {
- std::unique_ptr<MediaStreamUIProxy> ui_proxy = CreateMediaStreamUIProxy();
- ui_proxy->CheckAccess(
- subscriber.security_origin, type, render_process_id_,
- subscriber.render_frame_id,
- base::Bind(&MediaStreamDispatcherHost::HandleCheckAccessResponse,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(ui_proxy)),
- subscriber.render_frame_id));
- }
-}
-
bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcherHost, message)
@@ -121,18 +85,10 @@ bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
OnCancelGenerateStream)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StopStreamDevice,
OnStopStreamDevice)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_EnumerateDevices,
- OnEnumerateDevices)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelEnumerateDevices,
- OnCancelEnumerateDevices)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_OpenDevice,
OnOpenDevice)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CloseDevice,
OnCloseDevice)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_SubscribeToDeviceChangeNotifications,
- OnSubscribeToDeviceChangeNotifications)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelDeviceChangeNotifications,
- OnCancelDeviceChangeNotifications)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_SetCapturingLinkSecured,
OnSetCapturingLinkSecured)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -145,8 +101,6 @@ void MediaStreamDispatcherHost::OnChannelClosing() {
// Since the IPC sender is gone, close all requesting/requested streams.
media_stream_manager_->CancelAllRequests(render_process_id_);
- if (!device_change_subscribers_.empty())
- media_stream_manager_->CancelDeviceChangeNotifications(this);
}
MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
@@ -191,33 +145,6 @@ void MediaStreamDispatcherHost::OnStopStreamDevice(
device_id);
}
-void MediaStreamDispatcherHost::OnEnumerateDevices(
- int render_frame_id,
- int page_request_id,
- MediaStreamType type,
- const url::Origin& security_origin) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnEnumerateDevices("
- << render_frame_id << ", " << page_request_id << ", " << type << ", "
- << security_origin << ")";
-
- if (!MediaStreamManager::IsOriginAllowed(render_process_id_, security_origin))
- return;
-
- media_stream_manager_->EnumerateDevices(
- this, render_process_id_, render_frame_id, salt_, page_request_id, type,
- security_origin);
-}
-
-void MediaStreamDispatcherHost::OnCancelEnumerateDevices(
- int render_frame_id,
- int page_request_id) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices("
- << render_frame_id << ", "
- << page_request_id << ")";
- media_stream_manager_->CancelRequest(render_process_id_, render_frame_id,
- page_request_id);
-}
-
void MediaStreamDispatcherHost::OnOpenDevice(
int render_frame_id,
int page_request_id,
@@ -246,66 +173,6 @@ void MediaStreamDispatcherHost::OnCloseDevice(
media_stream_manager_->CancelRequest(label);
}
-void MediaStreamDispatcherHost::OnSubscribeToDeviceChangeNotifications(
- int render_frame_id,
- const url::Origin& security_origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1)
- << "MediaStreamDispatcherHost::OnSubscribeToDeviceChangeNotifications("
- << render_frame_id << ", " << security_origin << ")";
- DCHECK(
- std::find_if(
- device_change_subscribers_.begin(), device_change_subscribers_.end(),
- [render_frame_id](const DeviceChangeSubscriberInfo& subscriber_info) {
- return subscriber_info.render_frame_id == render_frame_id;
- }) == device_change_subscribers_.end());
-
- if (device_change_subscribers_.empty())
- media_stream_manager_->SubscribeToDeviceChangeNotifications(this);
-
- device_change_subscribers_.push_back({render_frame_id, security_origin});
-}
-
-void MediaStreamDispatcherHost::OnCancelDeviceChangeNotifications(
- int render_frame_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::CancelDeviceChangeNotifications("
- << render_frame_id << ")";
- auto it = std::find_if(
- device_change_subscribers_.begin(), device_change_subscribers_.end(),
- [render_frame_id](const DeviceChangeSubscriberInfo& subscriber_info) {
- return subscriber_info.render_frame_id == render_frame_id;
- });
- if (it == device_change_subscribers_.end()) {
- bad_message::ReceivedBadMessage(this, bad_message::MSDH_INVALID_FRAME_ID);
- return;
- }
- device_change_subscribers_.erase(it);
- if (device_change_subscribers_.empty())
- media_stream_manager_->CancelDeviceChangeNotifications(this);
-}
-
-std::unique_ptr<MediaStreamUIProxy>
-MediaStreamDispatcherHost::CreateMediaStreamUIProxy() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (use_fake_ui_ ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeUIForMediaStream)) {
- return base::MakeUnique<FakeMediaStreamUIProxy>();
- }
-
- return MediaStreamUIProxy::Create();
-}
-
-void MediaStreamDispatcherHost::HandleCheckAccessResponse(
- std::unique_ptr<MediaStreamUIProxy> ui_proxy,
- int render_frame_id,
- bool have_access) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (have_access)
- Send(new MediaStreamMsg_DevicesChanged(render_frame_id));
-}
-
void MediaStreamDispatcherHost::OnSetCapturingLinkSecured(int session_id,
MediaStreamType type,
bool is_secure) {
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 53195cc9404..158e1773f07 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
@@ -11,20 +11,19 @@
#include <vector>
#include "base/macros.h"
-#include "base/memory/weak_ptr.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_options.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/resource_context.h"
-#include "url/origin.h"
+namespace url {
+class Origin;
+}
namespace content {
class MediaStreamManager;
-class MediaStreamUIProxy;
-class ResourceContext;
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
// MediaStreamImpl. There is one MediaStreamDispatcherHost per
@@ -34,8 +33,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
public:
MediaStreamDispatcherHost(int render_process_id,
const std::string& salt,
- MediaStreamManager* media_stream_manager,
- bool use_fake_ui = false);
+ MediaStreamManager* media_stream_manager);
// MediaStreamRequester implementation.
void StreamGenerated(int render_frame_id,
@@ -50,15 +48,10 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
void DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) override;
- void DevicesEnumerated(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) override;
void DeviceOpened(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device) override;
- void DevicesChanged(MediaStreamType type) override;
// BrowserMessageFilter implementation.
bool OnMessageReceived(const IPC::Message& message) override;
@@ -80,14 +73,6 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
void OnStopStreamDevice(int render_frame_id,
const std::string& device_id);
- void OnEnumerateDevices(int render_frame_id,
- int page_request_id,
- MediaStreamType type,
- const url::Origin& security_origin);
-
- void OnCancelEnumerateDevices(int render_frame_id,
- int page_request_id);
-
void OnOpenDevice(int render_frame_id,
int page_request_id,
const std::string& device_id,
@@ -97,12 +82,6 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
void OnCloseDevice(int render_frame_id,
const std::string& label);
- void OnSubscribeToDeviceChangeNotifications(
- int render_frame_id,
- const url::Origin& security_origin);
-
- void OnCancelDeviceChangeNotifications(int render_frame_id);
-
void StoreRequest(int render_frame_id,
int page_request_id,
const std::string& label);
@@ -112,24 +91,10 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
content::MediaStreamType type,
bool is_secure);
- std::unique_ptr<MediaStreamUIProxy> CreateMediaStreamUIProxy();
- void HandleCheckAccessResponse(std::unique_ptr<MediaStreamUIProxy> ui_proxy,
- int render_frame_id,
- bool have_access);
-
int render_process_id_;
std::string salt_;
MediaStreamManager* media_stream_manager_;
- struct DeviceChangeSubscriberInfo {
- int render_frame_id;
- url::Origin security_origin;
- };
- std::vector<DeviceChangeSubscriberInfo> device_change_subscribers_;
- bool use_fake_ui_;
-
- base::WeakPtrFactory<MediaStreamDispatcherHost> weak_factory_;
-
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 1595e142a9e..e1b1f53128f 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
@@ -81,7 +81,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
const std::string& salt,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
MediaStreamManager* manager)
- : MediaStreamDispatcherHost(kProcessId, salt, manager, true),
+ : MediaStreamDispatcherHost(kProcessId, salt, manager),
task_runner_(task_runner),
current_ipc_(NULL) {}
@@ -122,35 +122,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
render_frame_id, page_request_id, device_id, type, security_origin);
}
- void OnEnumerateDevices(int render_frame_id,
- int page_request_id,
- MediaStreamType type,
- const url::Origin& security_origin,
- const base::Closure& quit_closure) {
- quit_closures_.push(quit_closure);
- MediaStreamDispatcherHost::OnEnumerateDevices(
- render_frame_id, page_request_id, type, security_origin);
- }
-
- void OnCancelEnumerateDevices(int render_frame_id, int page_request_id) {
- MediaStreamDispatcherHost::OnCancelEnumerateDevices(render_frame_id,
- page_request_id);
- }
-
- void OnSubscribeToDeviceChangeNotifications(
- int render_frame_id,
- const url::Origin& security_origin,
- const base::Closure& quit_closure) {
- quit_closures_.push(quit_closure);
- MediaStreamDispatcherHost::OnSubscribeToDeviceChangeNotifications(
- render_frame_id, security_origin);
- }
-
std::string label_;
StreamDeviceInfoArray audio_devices_;
StreamDeviceInfoArray video_devices_;
StreamDeviceInfo opened_device_;
- StreamDeviceInfoArray enumerated_devices_;
private:
~MockMediaStreamDispatcherHost() override {}
@@ -172,8 +147,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
OnStreamGenerationFailedInternal)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStoppedInternal)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpenedInternal)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, OnDevicesEnumerated)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesChanged, OnDevicesChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
@@ -234,20 +207,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
opened_device_ = device;
}
- void OnDevicesEnumerated(int request_id,
- const StreamDeviceInfoArray& devices) {
- base::Closure quit_closure = quit_closures_.front();
- quit_closures_.pop();
- task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
- enumerated_devices_ = devices;
- }
-
- void OnDevicesChanged() {
- base::Closure quit_closure = quit_closures_.front();
- quit_closures_.pop();
- task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
- }
-
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
IPC::Message* current_ipc_;
std::queue<base::Closure> quit_closures_;
@@ -386,32 +345,6 @@ class MediaStreamDispatcherHostTest : public testing::Test {
EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
}
- void EnumerateDevicesAndWaitForResult(int render_frame_id,
- int page_request_id,
- MediaStreamType type) {
- base::RunLoop run_loop;
- host_->OnEnumerateDevices(render_frame_id, page_request_id, type, origin_,
- run_loop.QuitClosure());
- run_loop.Run();
- ASSERT_FALSE(host_->enumerated_devices_.empty());
- EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_));
- EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_));
- // Enumeration requests must be cancelled manually.
- host_->OnCancelEnumerateDevices(render_frame_id, page_request_id);
- }
-
- void SubscribeToDeviceChangeNotificationsAndWaitForNotification(
- int render_frame_id) {
- base::RunLoop run_loop;
- host_->OnSubscribeToDeviceChangeNotifications(render_frame_id, origin_,
- run_loop.QuitClosure());
- // Simulate a change in the set of devices.
- video_capture_device_factory_->set_number_of_devices(5);
- media_stream_manager_->media_devices_manager()->OnDevicesChanged(
- base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
- run_loop.Run();
- }
-
bool DoesContainRawIds(const StreamDeviceInfoArray& devices) {
for (size_t i = 0; i < devices.size(); ++i) {
media::AudioDeviceNames::const_iterator audio_it =
@@ -949,42 +882,4 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
run_loop.Run();
}
-TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) {
- SetupFakeUI(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_AUDIO_CAPTURE);
- EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
-}
-
-TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) {
- SetupFakeUI(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE);
- EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
-}
-
-TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevicesNoAccess) {
- SetupFakeUI(false);
- stream_ui_->SetMicAccess(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_AUDIO_CAPTURE);
- EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
-}
-
-TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevicesNoAccess) {
- SetupFakeUI(false);
- stream_ui_->SetCameraAccess(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE);
- EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
-}
-
-TEST_F(MediaStreamDispatcherHostTest, DeviceChangeNotification) {
- SetupFakeUI(false);
- // warm up the cache
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE);
- SubscribeToDeviceChangeNotificationsAndWaitForNotification(kRenderId);
-}
-
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index df4566bb5dd..2eca6993e5b 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -155,12 +155,6 @@ void EnableHotwordEffect(const StreamControls& controls, int* effects) {
}
}
-// Clears the MediaStreamDevice.name from all devices in |devices|.
-void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
- for (content::StreamDeviceInfo& device_info : *devices)
- device_info.device.name.clear();
-}
-
bool CalledOnIOThread() {
// Check if this function call is on the IO thread, except for unittests where
// an IO thread might not have been created.
@@ -168,10 +162,6 @@ bool CalledOnIOThread() {
!BrowserThread::IsMessageLoopValid(BrowserThread::IO);
}
-GURL ConvertToGURL(const url::Origin& origin) {
- return origin.unique() ? GURL() : GURL(origin.Serialize());
-}
-
bool GetDeviceIDFromHMAC(const std::string& salt,
const url::Origin& security_origin,
const std::string& hmac_device_id,
@@ -197,8 +187,6 @@ MediaStreamType ConvertToMediaStreamType(MediaDeviceType type) {
return MEDIA_DEVICE_AUDIO_CAPTURE;
case MEDIA_DEVICE_TYPE_VIDEO_INPUT:
return MEDIA_DEVICE_VIDEO_CAPTURE;
- case MEDIA_DEVICE_TYPE_AUDIO_OUTPUT:
- return MEDIA_DEVICE_AUDIO_OUTPUT;
default:
NOTREACHED();
}
@@ -212,8 +200,6 @@ MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) {
return MEDIA_DEVICE_TYPE_AUDIO_INPUT;
case MEDIA_DEVICE_VIDEO_CAPTURE:
return MEDIA_DEVICE_TYPE_VIDEO_INPUT;
- case MEDIA_DEVICE_AUDIO_OUTPUT:
- return MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
default:
NOTREACHED();
}
@@ -221,25 +207,12 @@ MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) {
return NUM_MEDIA_DEVICE_TYPES;
}
-StreamDeviceInfoArray ConvertToStreamDeviceInfoArray(
- MediaStreamType stream_type,
- const MediaDeviceInfoArray& device_infos) {
- StreamDeviceInfoArray stream_devices;
- for (const auto& info : device_infos) {
- stream_devices.emplace_back(stream_type, info.label, info.device_id,
- info.group_id);
- }
-
- return stream_devices;
-}
-
MediaStreamDevices ConvertToMediaStreamDevices(
MediaStreamType stream_type,
const MediaDeviceInfoArray& device_infos) {
MediaStreamDevices devices;
for (const auto& info : device_infos) {
- devices.emplace_back(stream_type, info.device_id, info.label,
- info.group_id);
+ devices.emplace_back(stream_type, info.device_id, info.label);
}
return devices;
@@ -284,7 +257,6 @@ class MediaStreamManager::DeviceRequest {
void SetAudioType(MediaStreamType audio_type) {
DCHECK(IsAudioInputMediaType(audio_type) ||
- audio_type == MEDIA_DEVICE_AUDIO_OUTPUT ||
audio_type == MEDIA_NO_SERVICE);
audio_type_ = audio_type;
}
@@ -307,9 +279,9 @@ class MediaStreamManager::DeviceRequest {
target_frame_id_ = requesting_frame_id;
ui_request_.reset(new MediaStreamRequest(
requesting_process_id, requesting_frame_id, page_request_id,
- ConvertToGURL(security_origin), user_gesture, request_type,
+ security_origin.GetURL(), user_gesture, request_type,
requested_audio_device_id, requested_video_device_id, audio_type_,
- video_type_));
+ video_type_, controls.disable_local_echo));
}
// Creates a tab capture specific MediaStreamRequest object that is used by
@@ -321,8 +293,8 @@ class MediaStreamManager::DeviceRequest {
target_frame_id_ = target_render_frame_id;
ui_request_.reset(new MediaStreamRequest(
target_render_process_id, target_render_frame_id, page_request_id,
- ConvertToGURL(security_origin), user_gesture, request_type, "", "",
- audio_type_, video_type_));
+ security_origin.GetURL(), user_gesture, request_type, "", "",
+ audio_type_, video_type_, controls.disable_local_echo));
}
bool HasUIRequest() const { return ui_request_.get() != nullptr; }
@@ -348,7 +320,7 @@ class MediaStreamManager::DeviceRequest {
media_observer->OnMediaRequestStateChanged(
target_process_id_, target_frame_id_, page_request_id,
- ConvertToGURL(security_origin), stream_type, new_state);
+ security_origin.GetURL(), stream_type, new_state);
}
MediaRequestState state(MediaStreamType stream_type) const {
@@ -463,7 +435,6 @@ MediaStreamManager::~MediaStreamManager() {
DVLOG(1) << "~MediaStreamManager";
DCHECK(requests_.empty());
DCHECK(!device_task_runner_.get());
- DCHECK(device_change_subscribers_.empty());
base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
// The PowerMonitor instance owned by BrowserMainLoops always outlives the
@@ -539,6 +510,18 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
const std::string& label = AddRequest(request);
+ if (!generate_stream_test_callback_.is_null()) {
+ // The test callback is responsible to verify whether the |controls| is
+ // as expected. Then we need to finish getUserMedia and let Javascript
+ // access the result.
+ if (generate_stream_test_callback_.Run(controls)) {
+ FinalizeGenerateStream(label, request);
+ } else {
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_INVALID_STATE);
+ }
+ return;
+ }
+
// Post a task and handle the request asynchronously. The reason is that the
// requester won't have a label for the request until this function returns
// and thus can not handle a response. Using base::Unretained is safe since
@@ -576,16 +559,6 @@ void MediaStreamManager::CancelRequest(const std::string& label) {
return;
}
- if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
- // It isn't an ideal use of "CancelRequest" to make it a requirement
- // for enumeration requests to be deleted via "CancelRequest" _after_
- // the request has been successfully fulfilled.
- // See note in FinalizeEnumerateDevices for a recommendation on how
- // we should refactor this.
- DeleteRequest(label);
- return;
- }
-
// This is a request for opening one or more devices.
for (const StreamDeviceInfo& device_info : request->devices) {
const MediaRequestState state = request->state(device_info.device.type);
@@ -716,85 +689,6 @@ void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
}
}
-std::string MediaStreamManager::EnumerateDevices(
- MediaStreamRequester* requester,
- int render_process_id,
- int render_frame_id,
- const std::string& salt,
- int page_request_id,
- MediaStreamType type,
- const url::Origin& security_origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(requester);
- DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- type == MEDIA_DEVICE_VIDEO_CAPTURE ||
- type == MEDIA_DEVICE_AUDIO_OUTPUT);
-
- DeviceRequest* request =
- new DeviceRequest(requester, render_process_id, render_frame_id,
- page_request_id, security_origin,
- false, // user gesture
- MEDIA_ENUMERATE_DEVICES, StreamControls(), salt);
- if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT)
- request->SetAudioType(type);
- else if (IsVideoMediaType(type))
- request->SetVideoType(type);
-
- const std::string& label = AddRequest(request);
- // Post a task and handle the request asynchronously. The reason is that the
- // requester won't have a label for the request until this function returns
- // and thus can not handle a response. Using base::Unretained is safe since
- // MediaStreamManager is deleted on the UI thread, after the IO thread has
- // been stopped.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaStreamManager::DoEnumerateDevices,
- base::Unretained(this), label));
- return label;
-}
-
-void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeviceRequest* request = FindRequest(label);
- if (!request)
- return; // This can happen if the request has been canceled.
-
- if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
- DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
- request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED);
- MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
- devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
- media_devices_manager_->EnumerateDevices(
- devices_to_enumerate,
- base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
- base::Unretained(this), label));
- return;
- }
-
- StartEnumeration(request, label);
- DVLOG(1) << "Enumerate Devices ({label = " << label << "})";
-}
-
-void MediaStreamManager::AudioOutputDevicesEnumerated(
- const std::string& label,
- const MediaDeviceEnumeration& enumeration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- DeviceRequest* request = FindRequest(label);
- if (!request)
- return;
-
- DCHECK_EQ(MEDIA_DEVICE_AUDIO_OUTPUT, request->audio_type());
- DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED,
- request->state(MEDIA_DEVICE_AUDIO_OUTPUT));
- DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
- DCHECK(!request->ui_proxy.get());
- StreamDeviceInfoArray device_infos = ConvertToStreamDeviceInfoArray(
- MEDIA_DEVICE_AUDIO_OUTPUT, enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]);
- request->devices = device_infos;
- FinalizeEnumerateDevices(label, request);
-}
-
void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
@@ -945,13 +839,9 @@ void MediaStreamManager::TranslateDeviceIdToSourceId(
DeviceRequest* request,
MediaStreamDevice* device) {
if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
- request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT ||
request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
device->id = GetHMACForMediaDeviceID(request->salt,
request->security_origin, device->id);
- if (!device->group_id.empty())
- device->group_id = GetHMACForMediaDeviceID(
- request->salt, request->security_origin, device->group_id);
}
}
@@ -1071,12 +961,10 @@ void MediaStreamManager::PostRequestToUI(
MediaStreamDevices devices;
for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
- devices.emplace_back(audio_type, info.device_id, info.label,
- info.group_id);
+ devices.emplace_back(audio_type, info.device_id, info.label);
}
for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
- devices.emplace_back(video_type, info.device_id, info.label,
- info.group_id);
+ devices.emplace_back(video_type, info.device_id, info.label);
}
fake_ui_->SetAvailableDevices(devices);
@@ -1183,11 +1071,9 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
}
// Customize controls for a WebContents based capture.
- int target_render_process_id = 0;
- int target_render_frame_id = 0;
-
- bool has_valid_device_id = WebContentsMediaCaptureId::ExtractTabCaptureTarget(
- capture_device_id, &target_render_process_id, &target_render_frame_id);
+ content::WebContentsMediaCaptureId web_id;
+ bool has_valid_device_id =
+ WebContentsMediaCaptureId::Parse(capture_device_id, &web_id);
if (!has_valid_device_id ||
(request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
request->audio_type() != MEDIA_NO_SERVICE) ||
@@ -1195,16 +1081,19 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
request->video_type() != MEDIA_NO_SERVICE)) {
return false;
}
- request->tab_capture_device_id = capture_device_id;
+ web_id.disable_local_echo = request->controls.disable_local_echo;
+
+ request->tab_capture_device_id = web_id.ToString();
- request->CreateTabCaptureUIRequest(target_render_process_id,
- target_render_frame_id);
+ request->CreateTabCaptureUIRequest(web_id.render_process_id,
+ web_id.main_render_frame_id);
DVLOG(3) << "SetupTabCaptureRequest "
- << ", {capture_device_id = " << capture_device_id << "}"
- << ", {target_render_process_id = " << target_render_process_id
+ << ", {capture_device_id = " << capture_device_id << "}"
+ << ", {target_render_process_id = " << web_id.render_process_id
<< "}"
- << ", {target_render_frame_id = " << target_render_frame_id << "}";
+ << ", {target_render_frame_id = " << web_id.main_render_frame_id
+ << "}";
return true;
}
@@ -1329,96 +1218,6 @@ void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
label, requested_devices.front());
}
-void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
- DeviceRequest* request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
- DCHECK(((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
- request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) &&
- request->video_type() == MEDIA_NO_SERVICE) ||
- (request->audio_type() == MEDIA_NO_SERVICE &&
- request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE));
-
- for (StreamDeviceInfo& device_info : request->devices)
- TranslateDeviceIdToSourceId(request, &device_info.device);
-
- if (use_fake_ui_) {
- if (!fake_ui_)
- fake_ui_.reset(new FakeMediaStreamUIProxy());
- request->ui_proxy = std::move(fake_ui_);
- } else {
- DCHECK(!request->ui_proxy);
- request->ui_proxy = MediaStreamUIProxy::Create();
- }
-
- // Output label permissions are based on input permission.
- const MediaStreamType type =
- request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
- request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT
- ? MEDIA_DEVICE_AUDIO_CAPTURE
- : MEDIA_DEVICE_VIDEO_CAPTURE;
-
- request->ui_proxy->CheckAccess(
- request->security_origin,
- type,
- request->requesting_process_id,
- request->requesting_frame_id,
- base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse,
- base::Unretained(this),
- label));
-}
-
-void MediaStreamManager::HandleCheckMediaAccessResponse(
- const std::string& label,
- bool have_access) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- DeviceRequest* request = FindRequest(label);
- if (!request) {
- // This can happen if the request was cancelled.
- DVLOG(1) << "The request with label " << label << " does not exist.";
- return;
- }
-
- if (!have_access)
- ClearDeviceLabels(&request->devices);
-
- request->requester->DevicesEnumerated(
- request->requesting_frame_id,
- request->page_request_id,
- label,
- request->devices);
-
- // TODO(guidou):
- // Ideally enumeration requests should be deleted once they have been served
- // (as any request). However, this implementation mixes requests and
- // notifications together so enumeration requests are kept open by some
- // implementations (only Pepper?) and enumerations are done again when
- // device notifications are fired.
- // Implementations that just want to request the device list and be done
- // (e.g. DeviceRequestMessageFilter), they must (confusingly) call
- // CancelRequest() after the request has been fulfilled. This is not
- // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest)
- // and can lead to subtle bugs (requests not deleted at all deleted too
- // early).
- //
- // Basically, it is not clear that using requests as an additional layer on
- // top of device notifications is necessary or good.
- //
- // To add to this, MediaStreamManager currently relies on the external
- // implementations of MediaStreamRequester to delete enumeration requests via
- // CancelRequest and e.g. DeviceRequestMessageFilter does this. However the
- // Pepper implementation does not seem to to this at all (and from what I can
- // see, it is the only implementation that uses an enumeration request as a
- // notification mechanism).
- //
- // We should decouple notifications from enumeration requests and once that
- // has been done, remove the requirement to call CancelRequest() to delete
- // enumeration requests and uncomment the following line:
- //
- // DeleteRequest(label);
-}
-
void MediaStreamManager::FinalizeMediaAccessRequest(
const std::string& label,
DeviceRequest* request,
@@ -1586,9 +1385,6 @@ void MediaStreamManager::DevicesEnumerated(
bool requested[] = {requested_audio_input, requested_video_input};
MediaStreamType stream_types[] = {MEDIA_DEVICE_AUDIO_CAPTURE,
MEDIA_DEVICE_VIDEO_CAPTURE};
- MediaDeviceType device_types[] = {MEDIA_DEVICE_TYPE_AUDIO_INPUT,
- MEDIA_DEVICE_TYPE_VIDEO_INPUT};
-
for (size_t i = 0; i < arraysize(requested); ++i) {
if (!requested[i])
continue;
@@ -1596,14 +1392,6 @@ void MediaStreamManager::DevicesEnumerated(
DCHECK(request->audio_type() == stream_types[i] ||
request->video_type() == stream_types[i]);
if (request->state(stream_types[i]) == MEDIA_REQUEST_STATE_REQUESTED) {
- if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
- // MEDIA_ENUMERATE_DEVICES requests are always for a single type, so it
- // is OK to ignore any remaining iteration in this loop.
- ProcessEnumerationRequest(label, request, stream_types[i],
- enumeration[device_types[i]]);
- return;
- }
- // Not a MEDIA_ENUMERATE_DEVICES request.
request->SetState(stream_types[i], MEDIA_REQUEST_STATE_PENDING_APPROVAL);
}
}
@@ -1819,8 +1607,6 @@ void MediaStreamManager::NotifyDevicesChanged(
} else {
NOTREACHED();
}
-
- ProcessOpenEnumerationRequests(stream_type, devices);
}
bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
@@ -1901,33 +1687,6 @@ void MediaStreamManager::DoNativeLogCallbackUnregistration(
log_callbacks_.erase(renderer_host_id);
}
-void MediaStreamManager::SubscribeToDeviceChangeNotifications(
- MediaStreamRequester* subscriber) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(subscriber);
- DCHECK(std::find_if(device_change_subscribers_.begin(),
- device_change_subscribers_.end(),
- [subscriber](MediaStreamRequester* item) {
- return subscriber == item;
- }) == device_change_subscribers_.end());
- device_change_subscribers_.push_back(subscriber);
-}
-
-void MediaStreamManager::CancelDeviceChangeNotifications(
- MediaStreamRequester* subscriber) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto it = std::find(device_change_subscribers_.begin(),
- device_change_subscribers_.end(), subscriber);
- CHECK(it != device_change_subscribers_.end());
- device_change_subscribers_.erase(it);
-}
-
-void MediaStreamManager::NotifyDeviceChangeSubscribers(MediaStreamType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- for (auto* subscriber : device_change_subscribers_)
- subscriber->DevicesChanged(type);
-}
-
// static
std::string MediaStreamManager::GetHMACForMediaDeviceID(
const std::string& salt,
@@ -1964,8 +1723,9 @@ bool MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
bool MediaStreamManager::IsOriginAllowed(int render_process_id,
const url::Origin& origin) {
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
- render_process_id, ConvertToGURL(origin))) {
- LOG(ERROR) << "MSM: Renderer requested a URL it's not allowed to use.";
+ render_process_id, origin.GetURL())) {
+ LOG(ERROR) << "MSM: Renderer requested a URL it's not allowed to use: "
+ << origin.Serialize();
return false;
}
@@ -1992,47 +1752,9 @@ void MediaStreamManager::SetCapturingLinkSecured(int render_process_id,
}
}
-void MediaStreamManager::ProcessEnumerationRequest(
- const std::string& label,
- DeviceRequest* request,
- MediaStreamType stream_type,
- const MediaDeviceInfoArray& device_infos) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED, request->state(stream_type));
- DCHECK(request->audio_type() == stream_type ||
- request->video_type() == stream_type);
- DCHECK(request->audio_type() == MEDIA_NO_SERVICE ||
- request->video_type() == MEDIA_NO_SERVICE);
- DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
-
- if (request->requester && !request->ui_proxy) {
- request->devices =
- ConvertToStreamDeviceInfoArray(stream_type, device_infos);
- FinalizeEnumerateDevices(label, request);
- }
-}
-
-// This function is intended to support subscription-style device enumerations.
-// It is only supported for media capture devices and will be removed once
-// handling of enumeration requests and device-change notifications is migrated
-// out of MediaStreamManager.
-void MediaStreamManager::ProcessOpenEnumerationRequests(
- MediaStreamType stream_type,
- const MediaDeviceInfoArray& device_infos) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
-
- for (const LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* request = labeled_request.second;
- if (request->request_type == MEDIA_ENUMERATE_DEVICES &&
- request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
- (request->audio_type() == stream_type ||
- request->video_type() == stream_type)) {
- ProcessEnumerationRequest(labeled_request.first, request, stream_type,
- device_infos);
- }
- }
+void MediaStreamManager::SetGenerateStreamCallbackForTesting(
+ GenerateStreamTestCallback test_callback) {
+ generate_stream_test_callback_ = test_callback;
}
} // namespace content
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 28fb10286c3..60d60b6e045 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.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.
-// MediaStreamManager is used to open/enumerate media capture devices (video
-// supported now). Call flow:
+// MediaStreamManager is used to open media capture devices (video supported
+// now). Call flow:
// 1. GenerateStream is called when a render process wants to use a capture
// device.
// 2. MediaStreamManager will ask MediaStreamUIController for permission to
@@ -57,10 +57,7 @@ class Origin;
namespace content {
class AudioInputDeviceManager;
-class AudioOutputDeviceEnumerator;
-class BrowserContext;
class FakeMediaStreamUIProxy;
-class MediaStreamDeviceSettings;
class MediaStreamRequester;
class MediaStreamUIProxy;
class VideoCaptureManager;
@@ -78,6 +75,10 @@ class CONTENT_EXPORT MediaStreamManager
std::unique_ptr<MediaStreamUIProxy> ui)>
MediaRequestResponseCallback;
+ // Callback for testing.
+ typedef base::Callback<bool(const StreamControls&)>
+ GenerateStreamTestCallback;
+
// Adds |message| to native logs for outstanding device requests, for use by
// render processes hosts whose corresponding render processes are requesting
// logging from webrtcLoggingPrivate API. Safe to call from any thread.
@@ -139,21 +140,6 @@ class CONTENT_EXPORT MediaStreamManager
int render_frame_id,
const std::string& device_id);
- // Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE
- // or MEDIA_DEVICE_VIDEO_CAPTURE.
- // The request is identified using the string returned to the caller.
- // When the |requester| is NULL, MediaStreamManager will enumerate both audio
- // and video devices and also start monitoring device changes, such as
- // plug/unplug. The new device lists will be delivered via media observer to
- // MediaCaptureDevicesDispatcher.
- virtual std::string EnumerateDevices(MediaStreamRequester* requester,
- int render_process_id,
- int render_frame_id,
- const std::string& salt,
- int page_request_id,
- MediaStreamType type,
- const url::Origin& security_origin);
-
// Open a device identified by |device_id|. |type| must be either
// MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
// The request is identified using string returned to the caller.
@@ -226,15 +212,6 @@ class CONTENT_EXPORT MediaStreamManager
const base::Callback<void(const std::string&)>& callback);
void UnregisterNativeLogCallback(int renderer_host_id);
- // Register and unregister subscribers for device-change notifications.
- // It is an error to try to subscribe a |subscriber| that is already
- // subscribed or to cancel the subscription of a |subscriber| that is not
- // subscribed. Also, subscribers must make sure to invoke
- // CancelDeviceChangeNotifications() before destruction. Otherwise, dangling
- // pointers and use-after-destruction problems will occur.
- void SubscribeToDeviceChangeNotifications(MediaStreamRequester* subscriber);
- void CancelDeviceChangeNotifications(MediaStreamRequester* subscriber);
-
// Generates a hash of a device's unique ID usable by one
// particular security origin.
static std::string GetHMACForMediaDeviceID(const std::string& salt,
@@ -269,10 +246,8 @@ class CONTENT_EXPORT MediaStreamManager
// render process is notified.
void StopRemovedDevice(MediaDeviceType type, const MediaDeviceInfo& device);
- // TODO(guidou): Remove this function once handling for renderer requests for
- // device-event notifications is moved out of MediaStreamDispatcherHost.
- // See http://crbug.com/648183.
- void NotifyDeviceChangeSubscribers(MediaStreamType type);
+ void SetGenerateStreamCallbackForTesting(
+ GenerateStreamTestCallback test_callback);
private:
// Contains all data needed to keep track of requests.
@@ -288,7 +263,6 @@ class CONTENT_EXPORT MediaStreamManager
// thread and registers this as a listener with the device managers.
void InitializeDeviceManagersOnIOThread();
-
// |output_parameters| contains real values only if the request requires it.
void HandleAccessRequestResponse(
const std::string& label,
@@ -297,11 +271,6 @@ class CONTENT_EXPORT MediaStreamManager
content::MediaStreamRequestResult result);
void StopMediaStreamFromBrowser(const std::string& label);
- void DoEnumerateDevices(const std::string& label);
-
- void AudioOutputDevicesEnumerated(const std::string& label,
- const MediaDeviceEnumeration& enumeration);
-
// Helpers.
// Checks if all devices that was requested in the request identififed by
// |label| has been opened and set the request state accordingly.
@@ -367,8 +336,6 @@ class CONTENT_EXPORT MediaStreamManager
void FinalizeMediaAccessRequest(const std::string& label,
DeviceRequest* request,
const MediaStreamDevices& devices);
- void FinalizeEnumerateDevices(const std::string& label,
- DeviceRequest* request);
void HandleCheckMediaAccessResponse(const std::string& label,
bool have_access);
@@ -411,18 +378,6 @@ class CONTENT_EXPORT MediaStreamManager
const std::string& label,
const MediaDeviceEnumeration& enumeration);
- // TODO(guidou): Remove once handling of renderer-issued enumeration requests
- // is moved out of MediaStreamManager. See http://crbug.com/648183.
- void ProcessEnumerationRequest(const std::string& label,
- DeviceRequest* request,
- MediaStreamType stream_type,
- const MediaDeviceInfoArray& enumeration);
-
- // TODO(guidou): Remove this function once the concept of open enumeration
- // requests is eliminated. See http://crbug.com/648183.
- void ProcessOpenEnumerationRequests(MediaStreamType stream_type,
- const MediaDeviceInfoArray& devices);
-
// Task runner shared by VideoCaptureManager and AudioInputDeviceManager and
// used for enumerating audio output devices.
// Note: Enumeration tasks may take seconds to complete so must never be run
@@ -447,8 +402,7 @@ class CONTENT_EXPORT MediaStreamManager
// Maps render process hosts to log callbacks. Used on the IO thread.
std::map<int, base::Callback<void(const std::string&)>> log_callbacks_;
- // Objects subscribed to changes in the set of media devices.
- std::vector<MediaStreamRequester*> device_change_subscribers_;
+ GenerateStreamTestCallback generate_stream_test_callback_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
};
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index c2f0c11d64d..89accb6450a 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
@@ -132,19 +132,7 @@ class MockAudioManager : public AudioManagerPlatform {
class MockMediaStreamRequester : public MediaStreamRequester {
public:
- MockMediaStreamRequester(MediaStreamManager* media_stream_manager,
- base::RunLoop* run_loop_enumeration,
- size_t num_expected_devices,
- base::RunLoop* run_loop_devices_changed)
- : media_stream_manager_(media_stream_manager),
- run_loop_enumeration_(run_loop_enumeration),
- num_expected_devices_(num_expected_devices),
- run_loop_devices_changed_(run_loop_devices_changed),
- is_device_change_subscriber_(false) {}
- virtual ~MockMediaStreamRequester() {
- if (is_device_change_subscriber_)
- media_stream_manager_->CancelDeviceChangeNotifications(this);
- }
+ virtual ~MockMediaStreamRequester() {}
// MediaStreamRequester implementation.
MOCK_METHOD5(StreamGenerated,
@@ -161,47 +149,13 @@ class MockMediaStreamRequester : public MediaStreamRequester {
void(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device));
- void DevicesEnumerated(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) override {
- MockDevicesEnumerated(render_frame_id, page_request_id, label, devices);
- EXPECT_EQ(num_expected_devices_, devices.size());
-
- if (run_loop_enumeration_)
- run_loop_enumeration_->Quit();
- }
- MOCK_METHOD4(MockDevicesEnumerated,
- void(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices));
MOCK_METHOD4(DeviceOpened,
void(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& device_info));
- void DevicesChanged(MediaStreamType type) override {
- MockDevicesChanged(type);
- if (run_loop_devices_changed_)
- run_loop_devices_changed_->Quit();
- }
- MOCK_METHOD1(MockDevicesChanged, void(MediaStreamType type));
-
- void SubscribeToDeviceChangeNotifications() {
- if (is_device_change_subscriber_)
- return;
-
- media_stream_manager_->SubscribeToDeviceChangeNotifications(this);
- is_device_change_subscriber_ = true;
- }
private:
- MediaStreamManager* media_stream_manager_;
- base::RunLoop* run_loop_enumeration_;
- size_t num_expected_devices_;
- base::RunLoop* run_loop_devices_changed_;
- bool is_device_change_subscriber_;
DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
};
@@ -338,85 +292,4 @@ TEST_F(MediaStreamManagerTest, DeviceID) {
EXPECT_TRUE(base::IsAsciiDigit(c) || (c >= 'a' && c <= 'f'));
}
-TEST_F(MediaStreamManagerTest, EnumerationOutputDevices) {
- for (size_t num_devices = 0; num_devices < 3; num_devices++) {
- audio_manager_->SetNumAudioOutputDevices(num_devices);
- base::RunLoop run_loop;
- MockMediaStreamRequester requester(media_stream_manager_.get(), &run_loop,
- num_devices == 0 ? 0 : num_devices + 1,
- nullptr);
- const int render_process_id = 1;
- const int render_frame_id = 1;
- const int page_request_id = 1;
- const url::Origin security_origin(GURL("http://localhost"));
- EXPECT_CALL(requester,
- MockDevicesEnumerated(render_frame_id, page_request_id, _, _));
- std::string label = media_stream_manager_->EnumerateDevices(
- &requester, render_process_id, render_frame_id, kMockSalt,
- page_request_id, MEDIA_DEVICE_AUDIO_OUTPUT, security_origin);
- run_loop.Run();
- // CancelRequest is necessary for enumeration requests.
- media_stream_manager_->CancelRequest(label);
- }
-}
-
-TEST_F(MediaStreamManagerTest, NotifyDeviceChanges) {
- const int render_process_id = 1;
- const int render_frame_id = 1;
- const int page_request_id = 1;
- const url::Origin security_origin(GURL("http://localhost"));
-
- // Check that device change notifications are received
- {
- // First run an enumeration to warm up the cache
- base::RunLoop run_loop_enumeration;
- base::RunLoop run_loop_device_change;
- MockMediaStreamRequester requester(media_stream_manager_.get(),
- &run_loop_enumeration, 3,
- &run_loop_device_change);
- audio_manager_->SetNumAudioInputDevices(2);
- requester.SubscribeToDeviceChangeNotifications();
-
- EXPECT_CALL(requester,
- MockDevicesEnumerated(render_frame_id, page_request_id, _, _));
- EXPECT_CALL(requester, MockDevicesChanged(_)).Times(0);
- std::string label = media_stream_manager_->EnumerateDevices(
- &requester, render_process_id, render_frame_id, kMockSalt,
- page_request_id, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
- run_loop_enumeration.Run();
- media_stream_manager_->CancelRequest(label);
-
- // Simulate device change
- EXPECT_CALL(requester, MockDevicesChanged(_));
- audio_manager_->SetNumAudioInputDevices(3);
- media_stream_manager_->media_devices_manager()->OnDevicesChanged(
- base::SystemMonitor::DEVTYPE_AUDIO);
- run_loop_device_change.Run();
- }
-
- // Check that bogus device changes where devices have not changed
- // do not trigger a notification.
- {
- base::RunLoop run_loop;
- MockMediaStreamRequester requester(media_stream_manager_.get(), &run_loop,
- 4, &run_loop);
- requester.SubscribeToDeviceChangeNotifications();
-
- // Bogus OnDeviceChange, as devices have not changed. Should not trigger
- // notification.
- EXPECT_CALL(requester, MockDevicesChanged(_)).Times(0);
- media_stream_manager_->media_devices_manager()->OnDevicesChanged(
- base::SystemMonitor::DEVTYPE_AUDIO);
-
- // Do enumeration to be able to quit the RunLoop.
- EXPECT_CALL(requester,
- MockDevicesEnumerated(render_frame_id, page_request_id, _, _));
- std::string label = media_stream_manager_->EnumerateDevices(
- &requester, render_process_id, render_frame_id, kMockSalt,
- page_request_id, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
- run_loop.Run();
- media_stream_manager_->CancelRequest(label);
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_requester.h b/chromium/content/browser/renderer_host/media/media_stream_requester.h
index fc475dde09b..0a3c85d6d1b 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_requester.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_requester.h
@@ -34,19 +34,11 @@ class CONTENT_EXPORT MediaStreamRequester {
virtual void DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) = 0;
- // Called as a reply of a successful call to EnumerateDevices.
- virtual void DevicesEnumerated(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) = 0;
// Called as a reply of a successful call to OpenDevice.
virtual void DeviceOpened(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& device_info) = 0;
- // Called when the set of media devices has changed, provided the
- // MediaStreamRequester is subscribed and authorized to receive such messages.
- virtual void DevicesChanged(MediaStreamType type) = 0;
protected:
virtual ~MediaStreamRequester() {
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
index 94b96edca89..5805279559a 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
@@ -6,13 +6,12 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/media/media_stream_settings_requester.h"
#include "content/browser/renderer_host/media/media_stream_ui_controller.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/common/media_stream_request.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,11 +44,6 @@ class MediaStreamDeviceUIControllerTest
protected:
virtual void SetUp() {
- message_loop_.reset(new base::MessageLoopForIO);
- ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
- message_loop_.get()));
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
ui_controller_.reset(new MediaStreamUIController(this));
}
@@ -69,9 +63,7 @@ class MediaStreamDeviceUIControllerTest
std::string());
}
- std::unique_ptr<base::MessageLoop> message_loop_;
- std::unique_ptr<BrowserThreadImpl> ui_thread_;
- std::unique_ptr<BrowserThreadImpl> io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<MediaStreamUIController> ui_controller_;
private:
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 9997a76e3e9..051a6471268 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -19,14 +19,6 @@
namespace content {
-namespace {
-
-GURL ConvertToGURL(const url::Origin& origin) {
- return origin.unique() ? GURL() : GURL(origin.Serialize());
-}
-
-} // namespace
-
void SetAndCheckAncestorFlag(MediaStreamRequest* request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* rfh =
@@ -213,7 +205,7 @@ void MediaStreamUIProxy::CheckAccess(
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::CheckAccess, base::Unretained(core_.get()),
- ConvertToGURL(security_origin), type, render_process_id,
+ security_origin.GetURL(), type, render_process_id,
render_frame_id),
base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
weak_factory_.GetWeakPtr(), callback));
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 9fd8b7e4888..90fc678dda8 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -94,7 +94,7 @@ TEST_F(MediaStreamUIProxyTest, Deny) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ MEDIA_DEVICE_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -122,7 +122,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ MEDIA_DEVICE_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -158,7 +158,7 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ MEDIA_DEVICE_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -182,7 +182,7 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ MEDIA_DEVICE_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -228,7 +228,7 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
std::string(), std::string(), MEDIA_NO_SERVICE,
- MEDIA_DESKTOP_VIDEO_CAPTURE));
+ MEDIA_DESKTOP_VIDEO_CAPTURE, false));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
diff --git a/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.cc b/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.cc
index 3b564cd92bf..bf73b68b5a3 100644
--- a/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.cc
+++ b/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.cc
@@ -27,15 +27,18 @@ void* SharedMemoryBufferHandle::data(int plane) {
return tracker_->shared_memory_.memory();
}
-ClientBuffer SharedMemoryBufferHandle::AsClientBuffer(int plane) {
- NOTREACHED();
- return nullptr;
-}
-
#if defined(OS_POSIX) && !defined(OS_MACOSX)
base::FileDescriptor SharedMemoryBufferHandle::AsPlatformFile() {
return tracker_->shared_memory_.handle();
}
#endif
+bool SharedMemoryBufferHandle::IsBackedByVideoFrame() const {
+ return false;
+}
+
+scoped_refptr<media::VideoFrame> SharedMemoryBufferHandle::GetVideoFrame() {
+ return scoped_refptr<media::VideoFrame>();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.h b/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.h
index da299838d2b..eaa00917eca 100644
--- a/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.h
+++ b/chromium/content/browser/renderer_host/media/shared_memory_buffer_handle.h
@@ -24,10 +24,11 @@ class SharedMemoryBufferHandle : public media::VideoCaptureBufferHandle {
gfx::Size dimensions() const override;
size_t mapped_size() const override;
void* data(int plane) override;
- ClientBuffer AsClientBuffer(int plane) override;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
base::FileDescriptor AsPlatformFile() override;
#endif
+ bool IsBackedByVideoFrame() const override;
+ scoped_refptr<media::VideoFrame> GetVideoFrame() override;
private:
SharedMemoryBufferTracker* const tracker_;
diff --git a/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.cc b/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.cc
index af9235bec9b..2ac92b269e4 100644
--- a/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.cc
+++ b/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.cc
@@ -6,6 +6,7 @@
#include "base/memory/ptr_util.h"
#include "content/browser/renderer_host/media/shared_memory_buffer_handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
namespace content {
@@ -16,7 +17,7 @@ bool SharedMemoryBufferTracker::Init(const gfx::Size& dimensions,
media::VideoPixelFormat format,
media::VideoPixelStorage storage_type,
base::Lock* lock) {
- DVLOG(2) << "allocating ShMem of " << dimensions.ToString();
+ DVLOG(2) << __func__ << "allocating ShMem of " << dimensions.ToString();
set_dimensions(dimensions);
// |dimensions| can be 0x0 for trackers that do not require memory backing.
set_max_pixel_count(dimensions.GetArea());
@@ -35,18 +36,11 @@ SharedMemoryBufferTracker::GetBufferHandle() {
return base::MakeUnique<SharedMemoryBufferHandle>(this);
}
-bool SharedMemoryBufferTracker::ShareToProcess(
- base::ProcessHandle process_handle,
- base::SharedMemoryHandle* new_handle) {
- return shared_memory_.ShareToProcess(process_handle, new_handle);
-}
-
-bool SharedMemoryBufferTracker::ShareToProcess2(
- int plane,
- base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) {
- NOTREACHED();
- return false;
+mojo::ScopedSharedBufferHandle
+SharedMemoryBufferTracker::GetHandleForTransit() {
+ return mojo::WrapSharedMemoryHandle(
+ base::SharedMemory::DuplicateHandle(shared_memory_.handle()),
+ mapped_size_, false /* read_only */);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.h b/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.h
index 81504378a27..50ce37b7ce4 100644
--- a/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.h
+++ b/chromium/content/browser/renderer_host/media/shared_memory_buffer_tracker.h
@@ -21,11 +21,7 @@ class SharedMemoryBufferTracker final
base::Lock* lock) override;
std::unique_ptr<media::VideoCaptureBufferHandle> GetBufferHandle() override;
- bool ShareToProcess(base::ProcessHandle process_handle,
- base::SharedMemoryHandle* new_handle) override;
- bool ShareToProcess2(int plane,
- base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) override;
+ mojo::ScopedSharedBufferHandle GetHandleForTransit() override;
private:
friend class SharedMemoryBufferHandle;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
index e31d4462e7c..2d461f39f37 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -23,7 +23,6 @@
#include "cc/test/test_context_provider.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "components/display_compositor/buffer_queue.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "media/base/video_frame.h"
@@ -41,10 +40,7 @@ struct PixelFormatAndStorage {
static const PixelFormatAndStorage kCapturePixelFormatAndStorages[] = {
{media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU},
{media::PIXEL_FORMAT_ARGB, media::PIXEL_STORAGE_CPU},
-#if !defined(OS_ANDROID)
- {media::PIXEL_FORMAT_I420,
- media::PIXEL_STORAGE_GPUMEMORYBUFFER},
-#endif
+ {media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU},
};
static const int kTestBufferPoolSize = 3;
@@ -56,71 +52,6 @@ static const int kTestBufferPoolSize = 3;
class VideoCaptureBufferPoolTest
: public testing::TestWithParam<PixelFormatAndStorage> {
protected:
- // A GpuMemoryBuffer Mock to provide a trivial RGBA buffer as Map() backing.
- // We need to allocate on ctor and deallocate on dtor so that consecutive
- // Map()-Unmap() cycles yield the same underlying data pointer.
- class MockGpuMemoryBuffer : public gfx::GpuMemoryBuffer {
- public:
- explicit MockGpuMemoryBuffer(const gfx::Size& size)
- : size_(size),
- data_(new uint8_t[size_.GetArea() * 4]),
- mapped_(false) {}
- ~MockGpuMemoryBuffer() override { delete[] data_; }
-
- bool Map() override {
- EXPECT_FALSE(mapped_);
- mapped_ = true;
- return true;
- }
- void* memory(size_t plane) override {
- EXPECT_TRUE(mapped_);
- EXPECT_EQ(0u, plane);
- return static_cast<void*>(data_);
- }
- void Unmap() override {
- EXPECT_TRUE(mapped_);
- mapped_ = false;
- }
- gfx::Size GetSize() const override { return size_; }
- gfx::BufferFormat GetFormat() const override {
- return gfx::BufferFormat::BGRA_8888;
- }
- int stride(size_t plane) const override {
- EXPECT_EQ(0u, plane);
- return size_.width() * 4;
- }
- gfx::GpuMemoryBufferId GetId() const override {
- return gfx::GpuMemoryBufferId(0);
- }
- gfx::GpuMemoryBufferHandle GetHandle() const override {
- return gfx::GpuMemoryBufferHandle();
- }
- ClientBuffer AsClientBuffer() override { return nullptr; }
-
- private:
- const gfx::Size size_;
- uint8_t* const data_;
- bool mapped_;
- };
-
-#if !defined(OS_ANDROID)
- // The next two classes are needed to replicate the GpuMemoryBuffer allocation
- // on Browser side.
- class StubBrowserGpuMemoryBufferManager
- : public BrowserGpuMemoryBufferManager {
- public:
- StubBrowserGpuMemoryBufferManager() : BrowserGpuMemoryBufferManager(1, 1) {}
-
- std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) override {
- return base::MakeUnique<MockGpuMemoryBuffer>(size);
- }
- };
-#endif
-
// This is a generic Buffer tracker
class Buffer {
public:
@@ -145,12 +76,6 @@ class VideoCaptureBufferPoolTest
base::MakeUnique<VideoCaptureBufferTrackerFactoryImpl>(),
kTestBufferPoolSize)) {}
-#if !defined(OS_ANDROID)
- void SetUp() override {
- gpu_memory_buffer_manager_.reset(new StubBrowserGpuMemoryBufferManager);
- }
-#endif
-
void ExpectDroppedId(int expected_dropped_id) {
expected_dropped_id_ = expected_dropped_id;
}
@@ -195,10 +120,6 @@ class VideoCaptureBufferPoolTest
scoped_refptr<media::VideoCaptureBufferPool> pool_;
private:
-#if !defined(OS_ANDROID)
- std::unique_ptr<StubBrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(VideoCaptureBufferPoolTest);
};
@@ -227,12 +148,9 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
ASSERT_NE(nullptr, buffer3.get());
ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
- // GMB backed frames have their platform and format specific allocations.
- if (GetParam().pixel_storage != media::PIXEL_STORAGE_GPUMEMORYBUFFER) {
- ASSERT_LE(format_lo.ImageAllocationSize(), buffer1->mapped_size());
- ASSERT_LE(format_lo.ImageAllocationSize(), buffer2->mapped_size());
- ASSERT_LE(format_lo.ImageAllocationSize(), buffer3->mapped_size());
- }
+ ASSERT_LE(format_lo.ImageAllocationSize(), buffer1->mapped_size());
+ ASSERT_LE(format_lo.ImageAllocationSize(), buffer2->mapped_size());
+ ASSERT_LE(format_lo.ImageAllocationSize(), buffer3->mapped_size());
ASSERT_NE(nullptr, buffer1->data());
ASSERT_NE(nullptr, buffer2->data());
@@ -335,8 +253,7 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
buffer2 = ReserveBuffer(size_hi, GetParam());
ASSERT_NE(nullptr, buffer2.get());
- if (GetParam().pixel_storage != media::PIXEL_STORAGE_GPUMEMORYBUFFER)
- ASSERT_LE(format_hi.ImageAllocationSize(), buffer2->mapped_size());
+ ASSERT_LE(format_hi.ImageAllocationSize(), buffer2->mapped_size());
ASSERT_EQ(3, buffer2->id());
ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
void* const memory_pointer_hi = buffer2->data();
@@ -349,8 +266,7 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
<< "Decrease in resolution should not reallocate buffer";
ASSERT_NE(nullptr, buffer2.get());
ASSERT_EQ(3, buffer2->id());
- if (GetParam().pixel_storage != media::PIXEL_STORAGE_GPUMEMORYBUFFER)
- ASSERT_LE(format_lo.ImageAllocationSize(), buffer2->mapped_size());
+ ASSERT_LE(format_lo.ImageAllocationSize(), buffer2->mapped_size());
ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty";
ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization());
@@ -447,17 +363,6 @@ TEST_P(VideoCaptureBufferPoolTest, DoesNotResurrectIfPropertiesNotMatched) {
ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage);
ASSERT_EQ(nullptr, resurrected.get());
- // Expect that the buffer cannot be resurrected if the pixel storage does not
- // match.
- altered_format_or_storage = GetParam();
- altered_format_or_storage.pixel_storage =
- (altered_format_or_storage.pixel_storage == media::PIXEL_STORAGE_CPU)
- ? media::PIXEL_STORAGE_GPUMEMORYBUFFER
- : media::PIXEL_STORAGE_CPU;
- resurrected =
- ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage);
- ASSERT_EQ(nullptr, resurrected.get());
-
// Finally, check that the buffer CAN be resurrected if all properties match.
resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
ASSERT_NE(nullptr, resurrected.get());
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.cc
index 1d2831bf00b..e44f12bef86 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_tracker_factory_impl.cc
@@ -6,7 +6,6 @@
#include "base/memory/ptr_util.h"
-#include "content/browser/renderer_host/media/gpu_memory_buffer_tracker.h"
#include "content/browser/renderer_host/media/shared_memory_buffer_tracker.h"
namespace content {
@@ -14,14 +13,8 @@ namespace content {
std::unique_ptr<media::VideoCaptureBufferTracker>
VideoCaptureBufferTrackerFactoryImpl::CreateTracker(
media::VideoPixelStorage storage) {
- switch (storage) {
- case media::PIXEL_STORAGE_GPUMEMORYBUFFER:
- return base::MakeUnique<GpuMemoryBufferTracker>();
- case media::PIXEL_STORAGE_CPU:
- return base::MakeUnique<SharedMemoryBufferTracker>();
- }
- NOTREACHED();
- return std::unique_ptr<media::VideoCaptureBufferTracker>();
+ DCHECK_EQ(media::PIXEL_STORAGE_CPU, storage);
+ return base::MakeUnique<SharedMemoryBufferTracker>();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index c594c3bb11a..bf0d9d9c0a9 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -95,11 +95,11 @@ class VideoFrameReceiverOnIOThread : public media::VideoFrameReceiver {
void OnIncomingCapturedVideoFrame(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override {
+ scoped_refptr<media::VideoFrame> frame) override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoFrameReceiver::OnIncomingCapturedVideoFrame, receiver_,
- base::Passed(&buffer), frame));
+ base::Passed(&buffer), std::move(frame)));
}
void OnError() override {
@@ -129,12 +129,10 @@ class VideoFrameReceiverOnIOThread : public media::VideoFrameReceiver {
struct VideoCaptureController::ControllerClient {
ControllerClient(VideoCaptureControllerID id,
VideoCaptureControllerEventHandler* handler,
- base::ProcessHandle render_process,
media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params)
: controller_id(id),
event_handler(handler),
- render_process_handle(render_process),
session_id(session_id),
parameters(params),
session_closed(false),
@@ -146,8 +144,6 @@ struct VideoCaptureController::ControllerClient {
const VideoCaptureControllerID controller_id;
VideoCaptureControllerEventHandler* const event_handler;
- // Handle to the render process that will receive the capture buffers.
- const base::ProcessHandle render_process_handle;
const media::VideoCaptureSessionId session_id;
const media::VideoCaptureParams parameters;
@@ -206,7 +202,6 @@ VideoCaptureController::NewDeviceClient() {
void VideoCaptureController::AddClient(
VideoCaptureControllerID id,
VideoCaptureControllerEventHandler* event_handler,
- base::ProcessHandle render_process,
media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -218,10 +213,9 @@ void VideoCaptureController::AddClient(
// Check that requested VideoCaptureParams are valid and supported. If not,
// report an error immediately and punt.
if (!params.IsValid() ||
- params.requested_format.pixel_format != media::PIXEL_FORMAT_I420 ||
- (params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU &&
- params.requested_format.pixel_storage !=
- media::PIXEL_STORAGE_GPUMEMORYBUFFER)) {
+ !(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 ||
+ params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) ||
+ params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU) {
// Crash in debug builds since the renderer should not have asked for
// invalid or unsupported parameters.
LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: "
@@ -244,8 +238,8 @@ void VideoCaptureController::AddClient(
if (FindClient(id, event_handler, controller_clients_))
return;
- std::unique_ptr<ControllerClient> client = base::MakeUnique<ControllerClient>(
- id, event_handler, render_process, session_id, params);
+ std::unique_ptr<ControllerClient> client =
+ base::MakeUnique<ControllerClient>(id, event_handler, session_id, params);
// If we already have gotten frame_info from the device, repeat it to the new
// client.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
@@ -408,7 +402,7 @@ VideoCaptureController::~VideoCaptureController() {
void VideoCaptureController::OnIncomingCapturedVideoFrame(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<VideoFrame>& frame) {
+ scoped_refptr<VideoFrame> frame) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const int buffer_id = buffer->id();
DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
@@ -423,15 +417,14 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
new base::DictionaryValue());
frame->metadata()->MergeInternalValuesInto(metadata.get());
- // Only I420 pixel format is currently supported.
- DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_I420)
+ // Only I420 and Y16 pixel formats are currently supported.
+ DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
+ frame->format() == media::PIXEL_FORMAT_Y16)
<< "Unsupported pixel format: "
<< media::VideoPixelFormatToString(frame->format());
// Sanity-checks to confirm |frame| is actually being backed by |buffer|.
- DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM ||
- (frame->storage_type() ==
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS));
+ DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM);
DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer->data(0) &&
(frame->data(media::VideoFrame::kYPlane) <
(reinterpret_cast<const uint8_t*>(buffer->data(0)) +
@@ -512,35 +505,14 @@ void VideoCaptureController::DoNewBufferOnIOThread(
media::VideoCaptureDevice::Client::Buffer* buffer,
const scoped_refptr<media::VideoFrame>& frame) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const int buffer_id = buffer->id();
+ DCHECK_EQ(media::VideoFrame::STORAGE_SHMEM, frame->storage_type());
- switch (frame->storage_type()) {
- case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS: {
- std::vector<gfx::GpuMemoryBufferHandle> handles;
- const size_t num_planes = media::VideoFrame::NumPlanes(frame->format());
- for (size_t i = 0; i < num_planes; ++i) {
- gfx::GpuMemoryBufferHandle remote_handle;
- buffer_pool_->ShareToProcess2(
- buffer_id, i, client->render_process_handle, &remote_handle);
- handles.push_back(remote_handle);
- }
- client->event_handler->OnBufferCreated2(client->controller_id, handles,
- buffer->dimensions(), buffer_id);
- break;
- }
- case media::VideoFrame::STORAGE_SHMEM: {
- base::SharedMemoryHandle remote_handle;
- buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle,
- &remote_handle);
- client->event_handler->OnBufferCreated(
- client->controller_id, remote_handle, buffer->mapped_size(),
- buffer_id);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
+ const int buffer_id = buffer->id();
+ mojo::ScopedSharedBufferHandle handle =
+ buffer_pool_->GetHandleForTransit(buffer_id);
+ client->event_handler->OnBufferCreated(client->controller_id,
+ std::move(handle),
+ buffer->mapped_size(), buffer_id);
}
VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.h b/chromium/content/browser/renderer_host/media/video_capture_controller.h
index 25c826bbc11..8aaf97cdc9d 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -51,8 +51,8 @@
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/media/video_capture.h"
-#include "media/base/video_capture_types.h"
#include "media/capture/video/video_frame_receiver.h"
+#include "media/capture/video_capture_types.h"
namespace media {
class VideoCaptureBufferPool;
@@ -81,7 +81,6 @@ class CONTENT_EXPORT VideoCaptureController : public media::VideoFrameReceiver {
// to receive frames from the device until RemoveClient() is called.
void AddClient(VideoCaptureControllerID id,
VideoCaptureControllerEventHandler* event_handler,
- base::ProcessHandle render_process,
media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params);
@@ -131,7 +130,7 @@ class CONTENT_EXPORT VideoCaptureController : public media::VideoFrameReceiver {
// Implementation of media::VideoFrameReceiver interface:
void OnIncomingCapturedVideoFrame(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override;
+ scoped_refptr<media::VideoFrame> frame) override;
void OnError() override;
void OnLog(const std::string& message) override;
void OnBufferDestroyed(int buffer_id_to_drop) override;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 0ad2bbb2e18..b8a8a82bdf3 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -9,8 +9,8 @@
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/system/buffer.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
namespace media {
class VideoFrame;
@@ -23,6 +23,7 @@ typedef int VideoCaptureControllerID;
// VideoCaptureControllerEventHandler is the interface for
// VideoCaptureController to notify clients about the events such as
// BufferReady, FrameInfo, Error, etc.
+// TODO(mcasas): https://crbug.com/654176 merge back into VideoCaptureController
class CONTENT_EXPORT VideoCaptureControllerEventHandler {
public:
// An Error has occurred in the VideoCaptureDevice.
@@ -30,17 +31,10 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
// A buffer has been newly created.
virtual void OnBufferCreated(VideoCaptureControllerID id,
- base::SharedMemoryHandle handle,
+ mojo::ScopedSharedBufferHandle handle,
int length,
int buffer_id) = 0;
- // A GpuMemoryBuffer backed buffer has been newly created.
- virtual void OnBufferCreated2(
- VideoCaptureControllerID id,
- const std::vector<gfx::GpuMemoryBufferHandle>& handles,
- const gfx::Size& size,
- int buffer_id) = 0;
-
// A previously created buffer has been freed and will no longer be used.
virtual void OnBufferDestroyed(VideoCaptureControllerID id,
int buffer_id) = 0;
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 3f19667f4fc..21c5fbe6931 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
@@ -26,9 +26,9 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "media/base/video_capture_types.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_util.h"
+#include "media/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -51,10 +51,8 @@ class MockVideoCaptureControllerEventHandler
// These mock methods are delegated to by our fake implementation of
// VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
MOCK_METHOD1(DoBufferCreated, void(VideoCaptureControllerID));
- MOCK_METHOD1(DoBufferCreated2, void(VideoCaptureControllerID));
MOCK_METHOD1(DoBufferDestroyed, void(VideoCaptureControllerID));
- MOCK_METHOD2(DoI420BufferReady,
- void(VideoCaptureControllerID, const gfx::Size&));
+ MOCK_METHOD2(DoBufferReady, void(VideoCaptureControllerID, const gfx::Size&));
MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID));
MOCK_METHOD1(DoError, void(VideoCaptureControllerID));
@@ -62,28 +60,21 @@ class MockVideoCaptureControllerEventHandler
DoError(id);
}
void OnBufferCreated(VideoCaptureControllerID id,
- base::SharedMemoryHandle handle,
+ mojo::ScopedSharedBufferHandle handle,
int length, int buffer_id) override {
DoBufferCreated(id);
}
- void OnBufferCreated2(
- VideoCaptureControllerID id,
- const std::vector<gfx::GpuMemoryBufferHandle>& handles,
- const gfx::Size& size,
- int buffer_id) override {
- DoBufferCreated2(id);
- }
void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {
DoBufferDestroyed(id);
}
void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
const scoped_refptr<media::VideoFrame>& frame) override {
- EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420);
+ EXPECT_EQ(expected_pixel_format_, frame->format());
base::TimeTicks reference_time;
EXPECT_TRUE(frame->metadata()->GetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, &reference_time));
- DoI420BufferReady(id, frame->coded_size());
+ DoBufferReady(id, frame->coded_size());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureController::ReturnBuffer,
@@ -100,11 +91,14 @@ class MockVideoCaptureControllerEventHandler
}
VideoCaptureController* controller_;
+ media::VideoPixelFormat expected_pixel_format_ = media::PIXEL_FORMAT_I420;
double resource_utilization_;
};
// Test class.
-class VideoCaptureControllerTest : public testing::Test {
+class VideoCaptureControllerTest
+ : public testing::Test,
+ public testing::WithParamInterface<media::VideoPixelFormat> {
public:
VideoCaptureControllerTest() {}
~VideoCaptureControllerTest() override {}
@@ -123,13 +117,14 @@ class VideoCaptureControllerTest : public testing::Test {
void TearDown() override { base::RunLoop().RunUntilIdle(); }
- scoped_refptr<media::VideoFrame> WrapI420Buffer(gfx::Size dimensions,
- uint8_t* data) {
+ scoped_refptr<media::VideoFrame> WrapBuffer(
+ gfx::Size dimensions,
+ uint8_t* data,
+ media::VideoPixelFormat format = media::PIXEL_FORMAT_I420) {
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, dimensions, gfx::Rect(dimensions),
- dimensions, data, media::VideoFrame::AllocationSize(
- media::PIXEL_FORMAT_I420, dimensions),
+ format, dimensions, gfx::Rect(dimensions), dimensions, data,
+ media::VideoFrame::AllocationSize(format, dimensions),
base::SharedMemory::NULLHandle(), 0u, base::TimeDelta());
EXPECT_TRUE(video_frame);
return video_frame;
@@ -169,7 +164,6 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
<< "Client count should initially be zero.";
controller_->AddClient(client_a_route_1,
client_a_.get(),
- base::kNullProcessHandle,
100,
session_100);
// Clients in controller: [A/1]
@@ -177,7 +171,6 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
<< "Adding client A/1 should bump client count.";
controller_->AddClient(client_a_route_2,
client_a_.get(),
- base::kNullProcessHandle,
200,
session_200);
// Clients in controller: [A/1, A/2]
@@ -185,7 +178,6 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
<< "Adding client A/2 should bump client count.";
controller_->AddClient(client_b_route_1,
client_b_.get(),
- base::kNullProcessHandle,
300,
session_300);
// Clients in controller: [A/1, A/2, B/1]
@@ -208,7 +200,6 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
ASSERT_EQ(1, controller_->GetClientCount());
controller_->AddClient(client_b_route_2,
client_b_.get(),
- base::kNullProcessHandle,
400,
session_400);
// Clients in controller: [A/1, B/2]
@@ -248,10 +239,14 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
// This test will connect and disconnect several clients while simulating an
// active capture device being started and generating frames. It runs on one
// thread and is intended to behave deterministically.
-TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
+TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
media::VideoCaptureParams session_100;
- session_100.requested_format = media::VideoCaptureFormat(
- gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
+ const media::VideoPixelFormat format = GetParam();
+ client_a_->expected_pixel_format_ = format;
+ client_b_->expected_pixel_format_ = format;
+
+ session_100.requested_format =
+ media::VideoCaptureFormat(gfx::Size(320, 240), 30, format);
media::VideoCaptureParams session_200 = session_100;
@@ -274,17 +269,14 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Start with two clients.
controller_->AddClient(client_a_route_1,
client_a_.get(),
- base::kNullProcessHandle,
100,
session_100);
controller_->AddClient(client_b_route_1,
client_b_.get(),
- base::kNullProcessHandle,
300,
session_300);
controller_->AddClient(client_a_route_2,
client_a_.get(),
- base::kNullProcessHandle,
200,
session_200);
ASSERT_EQ(3, controller_->GetClientCount());
@@ -294,7 +286,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
uint8_t buffer_no = 1;
ASSERT_EQ(0.0, device_->GetBufferPoolUtilization());
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
- device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
+ device_->ReserveOutputBuffer(capture_resolution, format,
media::PIXEL_STORAGE_CPU));
ASSERT_TRUE(buffer.get());
ASSERT_EQ(1.0 / kPoolSize, device_->GetBufferPoolUtilization());
@@ -302,26 +294,23 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
{
InSequence s;
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_1, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution))
.Times(1);
}
{
InSequence s;
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_1, capture_resolution))
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution))
.Times(1);
}
{
InSequence s;
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_2, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution))
.Times(1);
}
- scoped_refptr<media::VideoFrame> video_frame =
- WrapI420Buffer(capture_resolution, static_cast<uint8_t*>(buffer->data()));
+ scoped_refptr<media::VideoFrame> video_frame = WrapBuffer(
+ capture_resolution, static_cast<uint8_t*>(buffer->data()), format);
ASSERT_TRUE(video_frame);
ASSERT_FALSE(video_frame->metadata()->HasKey(
media::VideoFrameMetadata::RESOURCE_UTILIZATION));
@@ -347,12 +336,12 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// case pretend that the Buffer pointer is held by the device for a long
// delay. This shouldn't affect anything.
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 =
- device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
+ device_->ReserveOutputBuffer(capture_resolution, format,
media::PIXEL_STORAGE_CPU);
ASSERT_TRUE(buffer2.get());
memset(buffer2->data(), buffer_no++, buffer2->mapped_size());
- video_frame = WrapI420Buffer(capture_resolution,
- static_cast<uint8_t*>(buffer2->data()));
+ video_frame = WrapBuffer(capture_resolution,
+ static_cast<uint8_t*>(buffer2->data()), format);
ASSERT_TRUE(video_frame);
ASSERT_FALSE(video_frame->metadata()->HasKey(
media::VideoFrameMetadata::RESOURCE_UTILIZATION));
@@ -366,22 +355,19 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
{
InSequence s;
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_1, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution))
.Times(1);
}
{
InSequence s;
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_1, capture_resolution))
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution))
.Times(1);
}
{
InSequence s;
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_2, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution))
.Times(1);
}
base::RunLoop().RunUntilIdle();
@@ -398,7 +384,6 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Add a fourth client now that some buffers have come through.
controller_->AddClient(client_b_route_2,
client_b_.get(),
- base::kNullProcessHandle,
1,
session_1);
Mock::VerifyAndClearExpectations(client_b_.get());
@@ -406,44 +391,39 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
for (int i = 0; i < kPoolSize; i++) {
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ device_->ReserveOutputBuffer(capture_resolution, format,
media::PIXEL_STORAGE_CPU);
ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->mapped_size());
- video_frame = WrapI420Buffer(capture_resolution,
- static_cast<uint8_t*>(buffer->data()));
+ video_frame = WrapBuffer(capture_resolution,
+ static_cast<uint8_t*>(buffer->data()), format);
ASSERT_TRUE(video_frame);
video_frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame);
}
// ReserveOutputBuffer ought to fail now, because the pool is depleted.
- ASSERT_FALSE(
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
- media::PIXEL_STORAGE_CPU).get());
+ ASSERT_FALSE(device_
+ ->ReserveOutputBuffer(capture_resolution, format,
+ media::PIXEL_STORAGE_CPU)
+ .get());
// The new client needs to be notified of the creation of |kPoolSize| buffers;
// the old clients only |kPoolSize - 2|.
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_2, capture_resolution))
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
.Times(kPoolSize - 2);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_1, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
.Times(kPoolSize - 2);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_2, capture_resolution))
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
.Times(kPoolSize - 2);
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_1, capture_resolution))
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution))
.Times(kPoolSize);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -457,19 +437,19 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
controller_->StopSession(300);
// Queue up another buffer.
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 =
- device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
+ device_->ReserveOutputBuffer(capture_resolution, format,
media::PIXEL_STORAGE_CPU);
ASSERT_TRUE(buffer3.get());
memset(buffer3->data(), buffer_no++, buffer3->mapped_size());
- video_frame = WrapI420Buffer(capture_resolution,
- static_cast<uint8_t*>(buffer3->data()));
+ video_frame = WrapBuffer(capture_resolution,
+ static_cast<uint8_t*>(buffer3->data()), format);
ASSERT_TRUE(video_frame);
video_frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
device_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame);
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 =
- device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
+ device_->ReserveOutputBuffer(capture_resolution, format,
media::PIXEL_STORAGE_CPU);
{
// Kill A2 via session close (posts a task to disconnect, but A2 must not
@@ -479,22 +459,26 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
}
ASSERT_TRUE(buffer4.get());
memset(buffer4->data(), buffer_no++, buffer4->mapped_size());
- video_frame = WrapI420Buffer(capture_resolution,
- static_cast<uint8_t*>(buffer4->data()));
+ video_frame = WrapBuffer(capture_resolution,
+ static_cast<uint8_t*>(buffer4->data()), format);
ASSERT_TRUE(video_frame);
video_frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
device_->OnIncomingCapturedVideoFrame(std::move(buffer4), video_frame);
// B2 is the only client left, and is the only one that should
// get the buffer.
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_2, capture_resolution))
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2, capture_resolution))
.Times(2);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
}
+INSTANTIATE_TEST_CASE_P(,
+ VideoCaptureControllerTest,
+ ::testing::Values(media::PIXEL_FORMAT_I420,
+ media::PIXEL_FORMAT_Y16));
+
// Exercises the OnError() codepath of VideoCaptureController, and tests the
// behavior of various operations after the error state has been signalled.
TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
@@ -509,8 +493,7 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
const VideoCaptureControllerID route_id(0x99);
// Start with one client.
- controller_->AddClient(
- route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
+ controller_->AddClient(route_id, client_a_.get(), 100, session_100);
device_->OnError(FROM_HERE, "Test Error");
EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
base::RunLoop().RunUntilIdle();
@@ -519,8 +502,7 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
// Second client connects after the error state. It also should get told of
// the error.
EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
- controller_->AddClient(
- route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
+ controller_->AddClient(route_id, client_b_.get(), 200, session_200);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_b_.get());
@@ -529,7 +511,7 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
media::PIXEL_STORAGE_CPU));
ASSERT_TRUE(buffer.get());
scoped_refptr<media::VideoFrame> video_frame =
- WrapI420Buffer(capture_resolution, static_cast<uint8_t*>(buffer->data()));
+ WrapBuffer(capture_resolution, static_cast<uint8_t*>(buffer->data()));
ASSERT_TRUE(video_frame);
video_frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
@@ -550,8 +532,7 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
const VideoCaptureControllerID route_id(0x99);
// Start with one client.
- controller_->AddClient(
- route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
+ controller_->AddClient(route_id, client_a_.get(), 100, session_100);
media::VideoCaptureFormat device_format(
gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
@@ -568,7 +549,7 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
ASSERT_TRUE(buffer.get());
scoped_refptr<media::VideoFrame> video_frame =
- WrapI420Buffer(dims, static_cast<uint8_t*>(buffer->data()));
+ WrapBuffer(dims, static_cast<uint8_t*>(buffer->data()));
ASSERT_TRUE(video_frame);
device_->OnError(FROM_HERE, "Test Error");
video_frame->metadata()->SetTimeTicks(
@@ -582,8 +563,7 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
// Second client connects after the error state. It also should get told of
// the error.
EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
- controller_->AddClient(
- route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
+ controller_->AddClient(route_id, client_b_.get(), 200, session_200);
Mock::VerifyAndClearExpectations(client_b_.get());
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
index 507af161386..020854b4f27 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
@@ -44,7 +44,7 @@ class MockVideoCaptureController : public VideoCaptureController {
void OnIncomingCapturedVideoFrame(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame) override {
+ scoped_refptr<media::VideoFrame> frame) override {
MockOnIncomingCapturedVideoFrame(frame->coded_size());
}
};
@@ -167,7 +167,8 @@ TEST_F(VideoCaptureDeviceClientTest, DataCaptureGoodPixelFormats) {
media::PIXEL_FORMAT_RGB24,
#endif
media::PIXEL_FORMAT_RGB32,
- media::PIXEL_FORMAT_ARGB
+ media::PIXEL_FORMAT_ARGB,
+ media::PIXEL_FORMAT_Y16,
};
for (media::VideoPixelFormat format : kSupportedFormats) {
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 de8e65d4df6..fc111e4263b 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
@@ -152,7 +152,7 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
decode_done_closure_ =
base::Bind(decode_done_cb_, base::Passed(&out_buffer), out_frame);
}
- decoder_->Decode(in_buffer, out_frame);
+ decoder_->Decode(in_buffer, std::move(out_frame));
#else
NOTREACHED();
#endif
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 7815e40a196..7603448bffe 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -11,21 +11,28 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
-#include "content/common/media/video_capture_messages.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
- : BrowserMessageFilter(VideoCaptureMsgStart),
- BrowserAssociatedInterface(this, this),
- media_stream_manager_(media_stream_manager) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ : media_stream_manager_(media_stream_manager),
+ weak_factory_(this) {
+ DVLOG(1) << __func__;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
-VideoCaptureHost::~VideoCaptureHost() {}
+// static
+void VideoCaptureHost::Create(MediaStreamManager* media_stream_manager,
+ mojom::VideoCaptureHostRequest request) {
+ DVLOG(1) << __func__;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ mojo::MakeStrongBinding(
+ base::MakeUnique<VideoCaptureHost>(media_stream_manager),
+ std::move(request));
+}
-void VideoCaptureHost::OnChannelClosing() {
- // Since the IPC sender is gone, close all requested VideoCaptureDevices.
+VideoCaptureHost::~VideoCaptureHost() {
for (auto it = controllers_.begin(); it != controllers_.end(); ) {
const base::WeakPtr<VideoCaptureController>& controller = it->second;
if (controller) {
@@ -42,39 +49,27 @@ void VideoCaptureHost::OnChannelClosing() {
}
}
-void VideoCaptureHost::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) {
- DVLOG(1) << "VideoCaptureHost::OnError";
+ DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoError, this, controller_id));
+ base::Bind(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
+ controller_id));
}
void VideoCaptureHost::OnBufferCreated(VideoCaptureControllerID controller_id,
- base::SharedMemoryHandle handle,
+ mojo::ScopedSharedBufferHandle handle,
int length,
int buffer_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (controllers_.find(controller_id) == controllers_.end())
return;
- Send(new VideoCaptureMsg_NewBuffer(controller_id, handle, length, buffer_id));
-}
-
-void VideoCaptureHost::OnBufferCreated2(
- VideoCaptureControllerID controller_id,
- const std::vector<gfx::GpuMemoryBufferHandle>& handles,
- const gfx::Size& size,
- int buffer_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (controllers_.find(controller_id) == controllers_.end())
- return;
-
- Send(new VideoCaptureMsg_NewBuffer2(controller_id, handles, size, buffer_id));
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
+ device_id_to_observer_map_[controller_id]->OnBufferCreated(
+ buffer_id, std::move(handle));
+ }
}
void VideoCaptureHost::OnBufferDestroyed(VideoCaptureControllerID controller_id,
@@ -83,7 +78,8 @@ void VideoCaptureHost::OnBufferDestroyed(VideoCaptureControllerID controller_id,
if (controllers_.find(controller_id) == controllers_.end())
return;
- Send(new VideoCaptureMsg_FreeBuffer(controller_id, buffer_id));
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id))
+ device_id_to_observer_map_[controller_id]->OnBufferDestroyed(buffer_id);
}
void VideoCaptureHost::OnBufferReady(
@@ -94,105 +90,94 @@ void VideoCaptureHost::OnBufferReady(
if (controllers_.find(controller_id) == controllers_.end())
return;
- VideoCaptureMsg_BufferReady_Params params;
- params.device_id = controller_id;
- params.buffer_id = buffer_id;
- params.timestamp = video_frame->timestamp();
- video_frame->metadata()->MergeInternalValuesInto(&params.metadata);
- params.pixel_format = video_frame->format();
- params.storage_type = video_frame->storage_type();
- params.coded_size = video_frame->coded_size();
- params.visible_rect = video_frame->visible_rect();
-
- Send(new VideoCaptureMsg_BufferReady(params));
+ if (!base::ContainsKey(device_id_to_observer_map_, controller_id))
+ return;
+
+ mojom::VideoFrameInfoPtr info = mojom::VideoFrameInfo::New();
+ info->timestamp = video_frame->timestamp();
+ video_frame->metadata()->MergeInternalValuesInto(&info->metadata);
+
+ DCHECK(media::PIXEL_FORMAT_I420 == video_frame->format() ||
+ media::PIXEL_FORMAT_Y16 == video_frame->format());
+ info->pixel_format = video_frame->format();
+ info->storage_type = media::PIXEL_STORAGE_CPU;
+ info->coded_size = video_frame->coded_size();
+ info->visible_rect = video_frame->visible_rect();
+
+ device_id_to_observer_map_[controller_id]->OnBufferReady(buffer_id,
+ std::move(info));
}
void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id) {
- DVLOG(1) << "VideoCaptureHost::OnEnded";
+ DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoEnded, this, controller_id));
+ base::Bind(&VideoCaptureHost::DoEnded, weak_factory_.GetWeakPtr(),
+ controller_id));
}
-void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) {
- DVLOG(1) << "VideoCaptureHost::DoError";
+void VideoCaptureHost::Start(int32_t device_id,
+ int32_t session_id,
+ const media::VideoCaptureParams& params,
+ mojom::VideoCaptureObserverPtr observer) {
+ DVLOG(1) << __func__ << " session_id=" << session_id
+ << ", device_id=" << device_id << ", format="
+ << media::VideoCaptureFormat::ToString(params.requested_format);
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (controllers_.find(controller_id) == controllers_.end())
+
+ DCHECK(!base::ContainsKey(device_id_to_observer_map_, device_id));
+ device_id_to_observer_map_[device_id] = std::move(observer);
+
+ const VideoCaptureControllerID controller_id(device_id);
+ if (controllers_.find(controller_id) != controllers_.end()) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::STARTED);
return;
+ }
- Send(new VideoCaptureMsg_StateChanged(controller_id,
- VIDEO_CAPTURE_STATE_ERROR));
- DeleteVideoCaptureController(controller_id, true);
+ controllers_[controller_id] = base::WeakPtr<VideoCaptureController>();
+ media_stream_manager_->video_capture_manager()->StartCaptureForClient(
+ session_id, params, controller_id, this,
+ base::Bind(&VideoCaptureHost::OnControllerAdded,
+ weak_factory_.GetWeakPtr(), device_id));
}
-void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) {
- DVLOG(1) << "VideoCaptureHost::DoEnded";
+void VideoCaptureHost::Stop(int32_t device_id) {
+ DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (controllers_.find(controller_id) == controllers_.end())
- return;
- Send(new VideoCaptureMsg_StateChanged(controller_id,
- VIDEO_CAPTURE_STATE_ENDED));
- DeleteVideoCaptureController(controller_id, false);
-}
+ VideoCaptureControllerID controller_id(device_id);
-///////////////////////////////////////////////////////////////////////////////
-// IPC Messages handler.
-bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost, message)
- IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
- IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume, OnResumeCapture)
- IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady,
- OnRendererFinishedWithBuffer)
- IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats,
- OnGetDeviceSupportedFormats)
- IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse,
- OnGetDeviceFormatsInUse)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
+ if (base::ContainsKey(device_id_to_observer_map_, device_id)) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::STOPPED);
+ }
+ device_id_to_observer_map_.erase(controller_id);
+
+ DeleteVideoCaptureController(controller_id, false);
}
-void VideoCaptureHost::OnStartCapture(int device_id,
- media::VideoCaptureSessionId session_id,
- const media::VideoCaptureParams& params) {
+void VideoCaptureHost::Pause(int32_t device_id) {
+ DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
- << " session_id=" << session_id << ", device_id=" << device_id
- << ", format="
- << media::VideoCaptureFormat::ToString(params.requested_format)
- << "@" << params.requested_format.frame_rate << " ("
- << (params.resolution_change_policy ==
- media::RESOLUTION_POLICY_FIXED_RESOLUTION
- ? "fixed resolution"
- : (params.resolution_change_policy ==
- media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO
- ? "fixed aspect ratio"
- : "variable resolution")) << ")";
+
VideoCaptureControllerID controller_id(device_id);
- if (controllers_.find(controller_id) != controllers_.end()) {
- Send(new VideoCaptureMsg_StateChanged(device_id,
- VIDEO_CAPTURE_STATE_ERROR));
+ auto it = controllers_.find(controller_id);
+ if (it == controllers_.end() || !it->second)
return;
- }
- controllers_[controller_id] = base::WeakPtr<VideoCaptureController>();
- media_stream_manager_->video_capture_manager()->StartCaptureForClient(
- session_id,
- params,
- PeerHandle(),
- controller_id,
- this,
- base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
+ media_stream_manager_->video_capture_manager()->PauseCaptureForClient(
+ it->second.get(), controller_id, this);
+ if (base::ContainsKey(device_id_to_observer_map_, device_id)) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::PAUSED);
+ }
}
-void VideoCaptureHost::OnResumeCapture(
- int device_id,
- media::VideoCaptureSessionId session_id,
- const media::VideoCaptureParams& params) {
+void VideoCaptureHost::Resume(int32_t device_id,
+ int32_t session_id,
+ const media::VideoCaptureParams& params) {
DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -203,98 +188,99 @@ void VideoCaptureHost::OnResumeCapture(
media_stream_manager_->video_capture_manager()->ResumeCaptureForClient(
session_id, params, it->second.get(), controller_id, this);
- Send(new VideoCaptureMsg_StateChanged(device_id,
- VIDEO_CAPTURE_STATE_RESUMED));
+ if (base::ContainsKey(device_id_to_observer_map_, device_id)) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::RESUMED);
+ }
}
-void VideoCaptureHost::OnRendererFinishedWithBuffer(
- int device_id,
- int buffer_id,
- const gpu::SyncToken& sync_token,
- double consumer_resource_utilization) {
+void VideoCaptureHost::RequestRefreshFrame(int32_t device_id) {
+ DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
VideoCaptureControllerID controller_id(device_id);
auto it = controllers_.find(controller_id);
- if (it != controllers_.end()) {
- const base::WeakPtr<VideoCaptureController>& controller = it->second;
- if (controller) {
- controller->ReturnBuffer(controller_id, this, buffer_id, sync_token,
- consumer_resource_utilization);
- }
+ if (it == controllers_.end())
+ return;
+
+ if (VideoCaptureController* controller = it->second.get()) {
+ media_stream_manager_->video_capture_manager()
+ ->RequestRefreshFrameForClient(controller);
}
}
-void VideoCaptureHost::OnGetDeviceSupportedFormats(
- int device_id,
- media::VideoCaptureSessionId session_id) {
+void VideoCaptureHost::ReleaseBuffer(int32_t device_id,
+ int32_t buffer_id,
+ const gpu::SyncToken& sync_token,
+ double consumer_resource_utilization) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ VideoCaptureControllerID controller_id(device_id);
+ auto it = controllers_.find(controller_id);
+ if (it == controllers_.end())
+ return;
+
+ const base::WeakPtr<VideoCaptureController>& controller = it->second;
+ if (controller) {
+ controller->ReturnBuffer(controller_id, this, buffer_id, sync_token,
+ consumer_resource_utilization);
+ }
+}
+
+void VideoCaptureHost::GetDeviceSupportedFormats(
+ int32_t device_id,
+ int32_t session_id,
+ const GetDeviceSupportedFormatsCallback& callback) {
DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- media::VideoCaptureFormats device_supported_formats;
+ media::VideoCaptureFormats supported_formats;
if (!media_stream_manager_->video_capture_manager()
- ->GetDeviceSupportedFormats(session_id,
- &device_supported_formats)) {
- DLOG(WARNING)
- << "Could not retrieve device supported formats for device_id="
- << device_id << " session_id=" << session_id;
+ ->GetDeviceSupportedFormats(session_id, &supported_formats)) {
+ DLOG(WARNING) << "Could not retrieve device supported formats";
}
- Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated(
- device_id, device_supported_formats));
+ callback.Run(supported_formats);
}
-void VideoCaptureHost::OnGetDeviceFormatsInUse(
- int device_id,
- media::VideoCaptureSessionId session_id) {
+void VideoCaptureHost::GetDeviceFormatsInUse(
+ int32_t device_id,
+ int32_t session_id,
+ const GetDeviceFormatsInUseCallback& callback) {
DVLOG(1) << __func__ << " " << device_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media::VideoCaptureFormats formats_in_use;
if (!media_stream_manager_->video_capture_manager()->GetDeviceFormatsInUse(
session_id, &formats_in_use)) {
- DVLOG(1) << "Could not retrieve device format(s) in use for device_id="
- << device_id << " session_id=" << session_id;
+ DLOG(WARNING) << "Could not retrieve device format(s) in use";
}
- Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id,
- formats_in_use));
-}
-
-void VideoCaptureHost::Stop(int32_t device_id) {
- DVLOG(1) << __func__ << " " << device_id;
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- VideoCaptureControllerID controller_id(device_id);
-
- Send(new VideoCaptureMsg_StateChanged(device_id,
- VIDEO_CAPTURE_STATE_STOPPED));
- DeleteVideoCaptureController(controller_id, false);
+ callback.Run(formats_in_use);
}
-void VideoCaptureHost::Pause(int32_t device_id) {
- DVLOG(1) << __func__ << " " << device_id;
+void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) {
+ DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- VideoCaptureControllerID controller_id(device_id);
- auto it = controllers_.find(controller_id);
- if (it == controllers_.end() || !it->second)
+ if (controllers_.find(controller_id) == controllers_.end())
return;
- media_stream_manager_->video_capture_manager()->PauseCaptureForClient(
- it->second.get(), controller_id, this);
- Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_PAUSED));
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
+ device_id_to_observer_map_[controller_id]->OnStateChanged(
+ mojom::VideoCaptureState::FAILED);
+ }
+
+ DeleteVideoCaptureController(controller_id, true);
}
-void VideoCaptureHost::RequestRefreshFrame(int32_t device_id) {
- DVLOG(1) << __func__ << " " << device_id;
+void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) {
+ DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- VideoCaptureControllerID controller_id(device_id);
- auto it = controllers_.find(controller_id);
- if (it == controllers_.end())
+ if (controllers_.find(controller_id) == controllers_.end())
return;
- if (VideoCaptureController* controller = it->second.get()) {
- media_stream_manager_->video_capture_manager()
- ->RequestRefreshFrameForClient(controller);
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
+ device_id_to_observer_map_[controller_id]->OnStateChanged(
+ mojom::VideoCaptureState::ENDED);
}
+
+ DeleteVideoCaptureController(controller_id, false);
}
void VideoCaptureHost::OnControllerAdded(
@@ -312,12 +298,19 @@ void VideoCaptureHost::OnControllerAdded(
}
if (!controller) {
- Send(new VideoCaptureMsg_StateChanged(device_id,
- VIDEO_CAPTURE_STATE_ERROR));
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::FAILED);
+ }
controllers_.erase(controller_id);
return;
}
+ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
+ device_id_to_observer_map_[device_id]->OnStateChanged(
+ mojom::VideoCaptureState::STARTED);
+ }
+
DCHECK(!it->second);
it->second = controller;
}
@@ -330,11 +323,13 @@ void VideoCaptureHost::DeleteVideoCaptureController(
if (it == controllers_.end())
return;
- if (it->second) {
- media_stream_manager_->video_capture_manager()->StopCaptureForClient(
- it->second.get(), controller_id, this, on_error);
- }
+ const base::WeakPtr<VideoCaptureController> controller = it->second;
controllers_.erase(it);
+ if (!controller)
+ return;
+
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ controller.get(), controller_id, this, on_error);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index df46a5dcd3a..71d6ebc384c 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -1,52 +1,6 @@
// 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.
-//
-// VideoCaptureHost serves video capture related messages from
-// VideoCaptureMessageFilter which lives inside the render process.
-//
-// This class is owned by RenderProcessHostImpl, and instantiated on UI
-// thread, but all other operations and method calls happen on IO thread.
-//
-// Here's an example of a typical IPC dialog for video capture:
-//
-// Renderer VideoCaptureHost
-// | |
-// | VideoCaptureHostMsg_Start > |
-// | < VideoCaptureMsg_StateChanged |
-// | (VIDEO_CAPTURE_STATE_STARTED) |
-// | < VideoCaptureMsg_NewBuffer(1) |
-// | < VideoCaptureMsg_NewBuffer(2) |
-// | < VideoCaptureMsg_NewBuffer(3) |
-// | |
-// | < VideoCaptureMsg_BufferReady(1) |
-// | < VideoCaptureMsg_BufferReady(2) |
-// | VideoCaptureHostMsg_BufferReady(1) > |
-// | < VideoCaptureMsg_BufferReady(3) |
-// | VideoCaptureHostMsg_BufferReady(2) > |
-// | < VideoCaptureMsg_BufferReady(1) |
-// | VideoCaptureHostMsg_BufferReady(3) > |
-// | < VideoCaptureMsg_BufferReady(2) |
-// | VideoCaptureHostMsg_BufferReady(1) > |
-// | ... |
-// | < VideoCaptureMsg_BufferReady(3) |
-// | |
-// | ... (resolution change) |
-// | < VideoCaptureMsg_FreeBuffer(1) | Buffers are re-allocated
-// | < VideoCaptureMsg_NewBuffer(4) | with a larger size, as
-// | < VideoCaptureMsg_BufferReady(4) | needed.
-// | VideoCaptureHostMsg_BufferReady(2) > |
-// | < VideoCaptureMsg_FreeBuffer(2) |
-// | < VideoCaptureMsg_NewBuffer(5) |
-// | < VideoCaptureMsg_BufferReady(5) |
-// | ... |
-// | |
-// | < VideoCaptureMsg_BufferReady |
-// | --------- StopCapture ---------> |
-// | VideoCaptureHostMsg_BufferReady > |
-// | < VideoCaptureMsg_StateChanged |
-// | (VIDEO_CAPTURE_STATE_STOPPED) |
-// v v
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_
@@ -61,36 +15,35 @@
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/video_capture.mojom.h"
-#include "content/public/browser/browser_associated_interface.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "ipc/ipc_message.h"
namespace content {
class MediaStreamManager;
+// VideoCaptureHost is the IO thread browser process communication endpoint
+// between a renderer process (which can initiate and receive a video capture
+// stream) and a VideoCaptureController in the browser process (which provides
+// the stream from a video device). Every remote client is identified via a
+// unique |device_id|, and is paired with a single VideoCaptureController.
class CONTENT_EXPORT VideoCaptureHost
- : public BrowserMessageFilter,
- public VideoCaptureControllerEventHandler,
- public BrowserAssociatedInterface<mojom::VideoCaptureHost>,
+ : public VideoCaptureControllerEventHandler,
public mojom::VideoCaptureHost {
public:
explicit VideoCaptureHost(MediaStreamManager* media_stream_manager);
- // BrowserMessageFilter implementation.
- void OnChannelClosing() override;
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
+ static void Create(MediaStreamManager* media_stream_manager,
+ mojom::VideoCaptureHostRequest request);
+
+ ~VideoCaptureHost() override;
+
+ private:
+ friend class VideoCaptureTest;
// VideoCaptureControllerEventHandler implementation.
void OnError(VideoCaptureControllerID id) override;
void OnBufferCreated(VideoCaptureControllerID id,
- base::SharedMemoryHandle handle,
+ mojo::ScopedSharedBufferHandle handle,
int length,
int buffer_id) override;
- void OnBufferCreated2(VideoCaptureControllerID id,
- const std::vector<gfx::GpuMemoryBufferHandle>& handles,
- const gfx::Size& size,
- int buffer_id) override;
void OnBufferDestroyed(VideoCaptureControllerID id,
int buffer_id) override;
void OnBufferReady(VideoCaptureControllerID id,
@@ -98,45 +51,41 @@ class CONTENT_EXPORT VideoCaptureHost
const scoped_refptr<media::VideoFrame>& frame) override;
void OnEnded(VideoCaptureControllerID id) override;
- private:
- friend class BrowserThread;
- friend class base::DeleteHelper<VideoCaptureHost>;
- friend class MockVideoCaptureHost;
- friend class VideoCaptureHostTest;
-
- void DoError(VideoCaptureControllerID id);
- void DoEnded(VideoCaptureControllerID id);
-
- ~VideoCaptureHost() override;
-
- // IPC message handlers.
- void OnStartCapture(int device_id,
- media::VideoCaptureSessionId session_id,
- const media::VideoCaptureParams& params);
- void OnResumeCapture(int device_id,
- media::VideoCaptureSessionId session_id,
- const media::VideoCaptureParams& params);
- void OnRendererFinishedWithBuffer(int device_id,
- int buffer_id,
- const gpu::SyncToken& sync_token,
- double consumer_resource_utilization);
- void OnGetDeviceSupportedFormats(
- int device_id,
- media::VideoCaptureSessionId capture_session_id);
- void OnGetDeviceFormatsInUse(int device_id,
- media::VideoCaptureSessionId capture_session_id);
-
// mojom::VideoCaptureHost implementation
+ void Start(int32_t device_id,
+ int32_t session_id,
+ const media::VideoCaptureParams& params,
+ mojom::VideoCaptureObserverPtr observer) override;
void Stop(int32_t device_id) override;
void Pause(int32_t device_id) override;
+ void Resume(int32_t device_id,
+ int32_t session_id,
+ const media::VideoCaptureParams& params) override;
void RequestRefreshFrame(int32_t device_id) override;
+ void ReleaseBuffer(int32_t device_id,
+ int32_t buffer_id,
+ const gpu::SyncToken& sync_token,
+ double consumer_resource_utilization) override;
+ void GetDeviceSupportedFormats(
+ int32_t device_id,
+ int32_t session_id,
+ const GetDeviceSupportedFormatsCallback& callback) override;
+ void GetDeviceFormatsInUse(
+ int32_t device_id,
+ int32_t session_id,
+ const GetDeviceFormatsInUseCallback& callback) override;
+ void DoError(VideoCaptureControllerID id);
+ void DoEnded(VideoCaptureControllerID id);
+
+ // Bound as callback for VideoCaptureManager::StartCaptureForClient().
void OnControllerAdded(
int device_id,
const base::WeakPtr<VideoCaptureController>& controller);
- // Deletes the controller and notifies the VideoCaptureManager. |on_error| is
- // true if this is triggered by VideoCaptureControllerEventHandler::OnError.
+ // Helper function that deletes the controller and tells VideoCaptureManager
+ // to StopCaptureForClient(). |on_error| is true if this is triggered by
+ // VideoCaptureControllerEventHandler::OnError.
void DeleteVideoCaptureController(VideoCaptureControllerID controller_id,
bool on_error);
@@ -148,6 +97,12 @@ class CONTENT_EXPORT VideoCaptureHost
std::map<VideoCaptureControllerID, base::WeakPtr<VideoCaptureController>>
controllers_;
+ // VideoCaptureObservers map, each one is used and should be valid between
+ // Start() and the corresponding Stop().
+ std::map<int32_t, mojom::VideoCaptureObserverPtr> device_id_to_observer_map_;
+
+ base::WeakPtrFactory<VideoCaptureHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost);
};
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
deleted file mode 100644
index 1e6caa0d3d7..00000000000
--- a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ /dev/null
@@ -1,568 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/video_capture_host.h"
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/location.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/strings/stringprintf.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/media_stream_manager.h"
-#include "content/browser/renderer_host/media/media_stream_requester.h"
-#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
-#include "content/browser/renderer_host/media/video_capture_manager.h"
-#include "content/common/media/video_capture_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/test/test_content_browser_client.h"
-#include "media/audio/audio_manager.h"
-#include "media/base/media_switches.h"
-#include "media/base/video_capture_types.h"
-#include "media/base/video_frame.h"
-#include "net/url_request/url_request_context.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/audio/cras_audio_handler.h"
-#endif
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::StrictMock;
-
-namespace content {
-
-// Id used to identify the capture session between renderer and
-// video_capture_host. This is an arbitrary value.
-static const int kDeviceId = 555;
-
-// Define to enable test where video is dumped to file.
-// #define DUMP_VIDEO
-
-// Define to use a real video capture device.
-// #define TEST_REAL_CAPTURE_DEVICE
-
-// Simple class used for dumping video to a file. This can be used for verifying
-// the output.
-class DumpVideo {
- public:
- DumpVideo() {}
- const gfx::Size& coded_size() const { return coded_size_; }
- void StartDump(const gfx::Size& coded_size) {
- base::FilePath file_name = base::FilePath(base::StringPrintf(
- FILE_PATH_LITERAL("dump_w%d_h%d.yuv"),
- coded_size.width(),
- coded_size.height()));
- file_.reset(base::OpenFile(file_name, "wb"));
- coded_size_ = coded_size;
- }
- void NewVideoFrame(const void* buffer) {
- if (file_.get() != NULL) {
- const int size = media::VideoFrame::AllocationSize(
- media::PIXEL_FORMAT_I420, coded_size_);
- ASSERT_EQ(1U, fwrite(buffer, size, 1, file_.get()));
- }
- }
-
- private:
- base::ScopedFILE file_;
- gfx::Size coded_size_;
-};
-
-class MockMediaStreamRequester : public MediaStreamRequester {
- public:
- MockMediaStreamRequester() {}
- virtual ~MockMediaStreamRequester() {}
-
- // MediaStreamRequester implementation.
- MOCK_METHOD5(StreamGenerated,
- void(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& audio_devices,
- const StreamDeviceInfoArray& video_devices));
- MOCK_METHOD3(StreamGenerationFailed,
- void(int render_frame_id,
- int page_request_id,
- content::MediaStreamRequestResult result));
- MOCK_METHOD3(DeviceStopped, void(int render_frame_id,
- const std::string& label,
- const StreamDeviceInfo& device));
- MOCK_METHOD4(DevicesEnumerated, void(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices));
- MOCK_METHOD4(DeviceOpened, void(int render_frame_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfo& device_info));
- MOCK_METHOD1(DevicesChanged, void(MediaStreamType type));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
-};
-
-class MockVideoCaptureHost : public VideoCaptureHost {
- public:
- MockVideoCaptureHost(MediaStreamManager* manager)
- : VideoCaptureHost(manager),
- return_buffers_(false),
- dump_video_(false) {}
-
- // A list of mock methods.
- MOCK_METHOD4(OnNewBufferCreated,
- void(int device_id,
- base::SharedMemoryHandle handle,
- int length,
- int buffer_id));
- MOCK_METHOD2(OnBufferFreed, void(int device_id, int buffer_id));
- MOCK_METHOD1(OnBufferFilled, void(int device_id));
- MOCK_METHOD2(OnStateChanged, void(int device_id, VideoCaptureState state));
-
- // Use class DumpVideo to write I420 video to file.
- void SetDumpVideo(bool enable) {
- dump_video_ = enable;
- }
-
- void SetReturnReceivedDibs(bool enable) {
- return_buffers_ = enable;
- }
-
- // Return Dibs we currently have received.
- void ReturnReceivedDibs(int device_id) {
- int handle = GetReceivedDib();
- while (handle) {
- this->OnRendererFinishedWithBuffer(device_id, handle, gpu::SyncToken(),
- -1.0);
- handle = GetReceivedDib();
- }
- }
-
- int GetReceivedDib() {
- if (filled_dib_.empty())
- return 0;
- auto it = filled_dib_.begin();
- int h = it->first;
- filled_dib_.erase(it);
-
- return h;
- }
-
- private:
- ~MockVideoCaptureHost() 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);
-
- // In this method we dispatch the messages to the according handlers as if
- // we are the renderer.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreatedDispatch)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferFreedDispatch)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilledDispatch)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChangedDispatch)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- EXPECT_TRUE(handled);
-
- delete message;
- return true;
- }
-
- // These handler methods do minimal things and delegate to the mock methods.
- void OnNewBufferCreatedDispatch(int device_id,
- base::SharedMemoryHandle handle,
- uint32_t length,
- int buffer_id) {
- OnNewBufferCreated(device_id, handle, length, buffer_id);
- std::unique_ptr<base::SharedMemory> dib =
- base::MakeUnique<base::SharedMemory>(handle, false);
- dib->Map(length);
- filled_dib_[buffer_id] = std::move(dib);
- }
-
- void OnBufferFreedDispatch(int device_id, int buffer_id) {
- OnBufferFreed(device_id, buffer_id);
-
- auto it = filled_dib_.find(buffer_id);
- ASSERT_TRUE(it != filled_dib_.end());
- filled_dib_.erase(it);
- }
-
- void OnBufferFilledDispatch(
- const VideoCaptureMsg_BufferReady_Params& params) {
- base::SharedMemory* dib = filled_dib_[params.buffer_id].get();
- ASSERT_TRUE(dib != NULL);
- if (dump_video_) {
- if (dumper_.coded_size().IsEmpty())
- dumper_.StartDump(params.coded_size);
- ASSERT_TRUE(dumper_.coded_size() == params.coded_size)
- << "Dump format does not handle variable resolution.";
- dumper_.NewVideoFrame(dib->memory());
- }
-
- OnBufferFilled(params.device_id);
- if (return_buffers_) {
- VideoCaptureHost::OnRendererFinishedWithBuffer(
- params.device_id, params.buffer_id, gpu::SyncToken(), -1.0);
- }
- }
-
- void OnStateChangedDispatch(int device_id, VideoCaptureState state) {
- OnStateChanged(device_id, state);
- }
-
- std::map<int, std::unique_ptr<base::SharedMemory>> filled_dib_;
- bool return_buffers_;
- bool dump_video_;
- media::VideoCaptureFormat format_;
- DumpVideo dumper_;
-};
-
-ACTION_P2(ExitMessageLoop, task_runner, quit_closure) {
- task_runner->PostTask(FROM_HERE, quit_closure);
-}
-
-// This is an integration test of VideoCaptureHost in conjunction with
-// MediaStreamManager, VideoCaptureManager, VideoCaptureController, and
-// VideoCaptureDevice.
-class VideoCaptureHostTest : public testing::Test {
- public:
- VideoCaptureHostTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- opened_session_id_(kInvalidMediaCaptureSessionId) {}
-
- void SetUp() override {
- SetBrowserClientForTesting(&browser_client_);
-
-#if defined(OS_CHROMEOS)
- chromeos::CrasAudioHandler::InitializeForTesting();
-#endif
-
- // Create our own MediaStreamManager.
- audio_manager_ = media::AudioManager::CreateForTesting(task_runner_);
-#ifndef TEST_REAL_CAPTURE_DEVICE
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kUseFakeDeviceForMediaStream);
-#endif
- media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
- media_stream_manager_->UseFakeUIForTests(
- std::unique_ptr<FakeMediaStreamUIProxy>());
-
- // Create a Host and connect it to a simulated IPC channel.
- host_ = new MockVideoCaptureHost(media_stream_manager_.get());
- host_->OnChannelConnected(base::GetCurrentProcId());
-
- OpenSession();
- }
-
- void TearDown() override {
- // Verifies and removes the expectations on host_ and
- // returns true iff successful.
- Mock::VerifyAndClearExpectations(host_.get());
- EXPECT_TRUE(host_->controllers_.empty());
-
- CloseSession();
-
- // Simulate closing the IPC sender.
- host_->OnChannelClosing();
-
- // Release the reference to the mock object. The object will be destructed
- // on the current message loop.
- host_ = NULL;
-
-#if defined(OS_CHROMEOS)
- chromeos::CrasAudioHandler::Shutdown();
-#endif
- }
-
- void OpenSession() {
- const int render_process_id = 1;
- const int render_frame_id = 1;
- const int page_request_id = 1;
- const url::Origin security_origin(GURL("http://test.com"));
-
- ASSERT_TRUE(opened_device_label_.empty());
-
- // Enumerate video devices.
- StreamDeviceInfoArray devices;
- {
- base::RunLoop run_loop;
- std::string label = media_stream_manager_->EnumerateDevices(
- &stream_requester_,
- render_process_id,
- render_frame_id,
- browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
- page_request_id,
- MEDIA_DEVICE_VIDEO_CAPTURE,
- security_origin);
- EXPECT_CALL(stream_requester_,
- DevicesEnumerated(render_frame_id, page_request_id, label, _))
- .Times(1)
- .WillOnce(DoAll(ExitMessageLoop(task_runner_, run_loop.QuitClosure()),
- SaveArg<3>(&devices)));
- run_loop.Run();
- Mock::VerifyAndClearExpectations(&stream_requester_);
- media_stream_manager_->CancelRequest(label);
- }
- ASSERT_FALSE(devices.empty());
- ASSERT_EQ(StreamDeviceInfo::kNoId, devices[0].session_id);
-
- // Open the first device.
- {
- base::RunLoop run_loop;
- StreamDeviceInfo opened_device;
- media_stream_manager_->OpenDevice(
- &stream_requester_,
- render_process_id,
- render_frame_id,
- browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
- page_request_id,
- devices[0].device.id,
- MEDIA_DEVICE_VIDEO_CAPTURE,
- security_origin);
- EXPECT_CALL(stream_requester_,
- DeviceOpened(render_frame_id, page_request_id, _, _))
- .Times(1)
- .WillOnce(DoAll(ExitMessageLoop(task_runner_, run_loop.QuitClosure()),
- SaveArg<2>(&opened_device_label_),
- SaveArg<3>(&opened_device)));
- run_loop.Run();
- Mock::VerifyAndClearExpectations(&stream_requester_);
- ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id);
- opened_session_id_ = opened_device.session_id;
- }
- }
-
- void CloseSession() {
- if (opened_device_label_.empty())
- return;
- media_stream_manager_->CancelRequest(opened_device_label_);
- opened_device_label_.clear();
- opened_session_id_ = kInvalidMediaCaptureSessionId;
- }
-
- protected:
- void StartCapture() {
- EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Return());
-
- base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId))
- .Times(AnyNumber())
- .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
-
- media::VideoCaptureParams params;
- params.requested_format = media::VideoCaptureFormat(
- gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
- host_->OnStartCapture(kDeviceId, opened_session_id_, params);
- run_loop.Run();
- }
-
- void StartStopCapture() {
- // Quickly start and then stop capture, without giving much chance for
- // asynchronous start operations to complete.
- InSequence s;
- base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
- media::VideoCaptureParams params;
- params.requested_format = media::VideoCaptureFormat(
- gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
- host_->OnStartCapture(kDeviceId, opened_session_id_, params);
- host_->Stop(kDeviceId);
- run_loop.RunUntilIdle();
- WaitForVideoDeviceThread();
- }
-
- void PauseResumeCapture() {
- InSequence s;
- base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_PAUSED));
- host_->Pause(kDeviceId);
-
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_RESUMED));
- media::VideoCaptureParams params;
- params.requested_format = media::VideoCaptureFormat(
- gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
- host_->OnResumeCapture(kDeviceId, opened_session_id_, params);
- run_loop.RunUntilIdle();
- WaitForVideoDeviceThread();
- }
-
-#ifdef DUMP_VIDEO
- void CaptureAndDumpVideo(int width, int height, int frame_rate) {
- InSequence s;
- EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
- .Times(AnyNumber()).WillRepeatedly(Return());
-
- base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _, _, _, _, _, _, _))
- .Times(AnyNumber())
- .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
-
- media::VideoCaptureParams params;
- params.requested_format =
- media::VideoCaptureFormat(gfx::Size(width, height), frame_rate);
- host_->SetDumpVideo(true);
- host_->OnStartCapture(kDeviceId, opened_session_id_, params);
- run_loop.Run();
- }
-#endif
-
- void StopCapture() {
- base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
- .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
-
- host_->Stop(kDeviceId);
- host_->SetReturnReceivedDibs(true);
- host_->ReturnReceivedDibs(kDeviceId);
-
- run_loop.Run();
-
- host_->SetReturnReceivedDibs(false);
- // Expect the VideoCaptureDevice has been stopped
- EXPECT_TRUE(host_->controllers_.empty());
- }
-
- void NotifyPacketReady() {
- base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId))
- .Times(AnyNumber())
- .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()))
- .RetiresOnSaturation();
- run_loop.Run();
- }
-
- void ReturnReceivedPackets() {
- host_->ReturnReceivedDibs(kDeviceId);
- }
-
- void SimulateError() {
- // Expect a change state to error state sent through IPC.
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR)).Times(1);
- VideoCaptureControllerID id(kDeviceId);
- host_->OnError(id);
- // Wait for the error callback.
- base::RunLoop().RunUntilIdle();
- }
-
- void WaitForVideoDeviceThread() {
- base::RunLoop run_loop;
- media_stream_manager_->video_capture_manager()->device_task_runner()
- ->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&base::DoNothing),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- scoped_refptr<MockVideoCaptureHost> host_;
-
- private:
- // |media_stream_manager_| needs to outlive |thread_bundle_| because it is a
- // MessageLoop::DestructionObserver. |audio_manager_| needs to outlive
- // |thread_bundle_| because it uses the underlying message loop.
- StrictMock<MockMediaStreamRequester> stream_requester_;
- std::unique_ptr<MediaStreamManager> media_stream_manager_;
- const content::TestBrowserThreadBundle thread_bundle_;
- media::ScopedAudioManagerPtr audio_manager_;
- content::TestBrowserContext browser_context_;
- content::TestContentBrowserClient browser_client_;
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- int opened_session_id_;
- std::string opened_device_label_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
-};
-
-TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) {
- StartCapture();
-
- // When the session is closed via the stream without stopping capture, the
- // ENDED event is sent.
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED)).Times(1);
- CloseSession();
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(VideoCaptureHostTest, StopWhileStartPending) {
- StartStopCapture();
-}
-
-TEST_F(VideoCaptureHostTest, StartCapturePlayStop) {
- StartCapture();
- NotifyPacketReady();
- NotifyPacketReady();
- ReturnReceivedPackets();
- StopCapture();
-}
-
-TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) {
- StartCapture();
- SimulateError();
- StopCapture();
-}
-
-TEST_F(VideoCaptureHostTest, StartCaptureError) {
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)).Times(0);
- StartCapture();
- NotifyPacketReady();
- SimulateError();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
-}
-
-#ifdef DUMP_VIDEO
-TEST_F(VideoCaptureHostTest, CaptureAndDumpVideoVga) {
- CaptureAndDumpVideo(640, 480, 30);
-}
-TEST_F(VideoCaptureHostTest, CaptureAndDump720P) {
- CaptureAndDumpVideo(1280, 720, 30);
-}
-#endif
-
-TEST_F(VideoCaptureHostTest, PauseResumeCapture) {
- StartCapture();
- PauseResumeCapture();
- StopCapture();
-}
-
-} // namespace content
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 c3a7b8ac679..8ce5a592c86 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -34,14 +34,15 @@
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video/video_capture_device_factory.h"
-#if defined(ENABLE_SCREEN_CAPTURE)
+#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
#include "content/browser/media/capture/desktop_capture_device.h"
#if defined(USE_AURA)
#include "content/browser/media/capture/desktop_capture_device_aura.h"
#endif
-#if defined(OS_ANDROID)
-#include "content/browser/media/capture/screen_capture_device_android.h"
#endif
+
+#if defined(ENABLE_SCREEN_CAPTURE) && defined(OS_ANDROID)
+#include "content/browser/media/capture/screen_capture_device_android.h"
#endif
#if defined(OS_MACOSX)
@@ -88,9 +89,10 @@ void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
formats->erase(last, formats->end());
// Mark all formats as I420, since this is what the renderer side will get
// anyhow: the actual pixel format is decided at the device level.
- for (media::VideoCaptureFormats::iterator it = formats->begin();
- it != formats->end(); ++it) {
- it->pixel_format = media::PIXEL_FORMAT_I420;
+ // Don't do this for Y16 format as it is handled separatelly.
+ for (auto& format : *formats) {
+ if (format.pixel_format != media::PIXEL_FORMAT_Y16)
+ format.pixel_format = media::PIXEL_FORMAT_I420;
}
}
@@ -519,9 +521,9 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
void VideoCaptureManager::OnDeviceStarted(
int serial_id,
std::unique_ptr<VideoCaptureDevice> device) {
+ DVLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(serial_id, device_start_queue_.begin()->serial_id());
- DVLOG(3) << __func__;
if (device_start_queue_.front().abort_start()) {
// |device| can be null if creation failed in
// DoStartDeviceCaptureOnDeviceThread.
@@ -548,13 +550,14 @@ void VideoCaptureManager::OnDeviceStarted(
MaybePostDesktopCaptureWindowId(session_id);
}
- auto request = photo_request_queue_.begin();
- while(request != photo_request_queue_.end()) {
- if (GetDeviceEntryBySessionId(request->first)->video_capture_device()) {
- request->second.Run(entry->video_capture_device());
+ auto it = photo_request_queue_.begin();
+ while (it != photo_request_queue_.end()) {
+ auto request = it++;
+ DeviceEntry* maybe_entry = GetDeviceEntryBySessionId(request->first);
+ if (maybe_entry && maybe_entry->video_capture_device()) {
+ request->second.Run(maybe_entry->video_capture_device());
photo_request_queue_.erase(request);
}
- ++request;
}
}
@@ -592,7 +595,7 @@ VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
DCHECK(IsOnDeviceThread());
std::unique_ptr<VideoCaptureDevice> video_capture_device;
- video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id));
+ video_capture_device = WebContentsVideoCaptureDevice::Create(id);
if (!video_capture_device) {
device_client->OnError(FROM_HERE, "Could not create capture device");
@@ -620,7 +623,7 @@ VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
}
if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
- video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id));
+ video_capture_device = WebContentsVideoCaptureDevice::Create(id);
IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
if (desktop_id.audio_share) {
IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO);
@@ -630,11 +633,13 @@ VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
} else {
#if defined(OS_ANDROID)
video_capture_device = base::MakeUnique<ScreenCaptureDeviceAndroid>();
-#elif defined(USE_AURA)
+#else
+#if defined(USE_AURA)
video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
-#endif
+#endif // defined(USE_AURA)
if (!video_capture_device)
video_capture_device = DesktopCaptureDevice::Create(desktop_id);
+#endif // defined (OS_ANDROID)
}
#endif // defined(ENABLE_SCREEN_CAPTURE)
@@ -650,7 +655,6 @@ VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
void VideoCaptureManager::StartCaptureForClient(
media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params,
- base::ProcessHandle client_render_process,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
const DoneCB& done_cb) {
@@ -678,7 +682,7 @@ void VideoCaptureManager::StartCaptureForClient(
// Run the callback first, as AddClient() may trigger OnFrameInfo().
done_cb.Run(entry->video_capture_controller()->GetWeakPtrForIOThread());
entry->video_capture_controller()->AddClient(
- client_id, client_handler, client_render_process, session_id, params);
+ client_id, client_handler, session_id, params);
}
void VideoCaptureManager::StopCaptureForClient(
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.h b/chromium/content/browser/renderer_host/media/video_capture_manager.h
index 899e2788f92..cc309de1b7a 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -29,9 +29,9 @@
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
-#include "media/base/video_capture_types.h"
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video/video_capture_device_factory.h"
+#include "media/capture/video_capture_types.h"
#if defined(OS_ANDROID)
#include "base/android/application_status_listener.h"
@@ -76,7 +76,6 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// the callback on failure.
void StartCaptureForClient(media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& capture_params,
- base::ProcessHandle client_render_process,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
const DoneCB& done_cb);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 9ec3c4453e8..5c27849ccaf 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -18,10 +18,11 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "content/browser/browser_thread_impl.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/media/media_stream_options.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -138,12 +139,8 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
MOCK_METHOD1(OnError, void(VideoCaptureControllerID id));
void OnBufferCreated(VideoCaptureControllerID id,
- base::SharedMemoryHandle handle,
+ mojo::ScopedSharedBufferHandle handle,
int length, int buffer_id) override {}
- void OnBufferCreated2(VideoCaptureControllerID id,
- const std::vector<gfx::GpuMemoryBufferHandle>& handles,
- const gfx::Size& size,
- int buffer_id) override {}
void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {}
void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
@@ -176,11 +173,6 @@ class VideoCaptureManagerTest : public testing::Test {
protected:
void SetUp() override {
listener_.reset(new MockMediaStreamProviderListener());
- message_loop_.reset(new base::MessageLoopForIO);
- ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
- message_loop_.get()));
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
vcm_ = new VideoCaptureManager(
std::unique_ptr<media::VideoCaptureDeviceFactory>(
new WrappedDeviceFactory()));
@@ -188,7 +180,7 @@ class VideoCaptureManagerTest : public testing::Test {
vcm_->video_capture_device_factory());
const int32_t kNumberOfFakeDevices = 2;
video_capture_device_factory_->set_number_of_devices(kNumberOfFakeDevices);
- vcm_->Register(listener_.get(), message_loop_->task_runner().get());
+ vcm_->Register(listener_.get(), base::ThreadTaskRunnerHandle::Get());
frame_observer_.reset(new MockFrameObserver());
base::RunLoop run_loop;
@@ -223,7 +215,6 @@ class VideoCaptureManagerTest : public testing::Test {
vcm_->StartCaptureForClient(
session_id,
params,
- base::kNullProcessHandle,
client_id,
frame_observer_.get(),
base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback,
@@ -274,9 +265,7 @@ class VideoCaptureManagerTest : public testing::Test {
std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
scoped_refptr<VideoCaptureManager> vcm_;
std::unique_ptr<MockMediaStreamProviderListener> listener_;
- std::unique_ptr<base::MessageLoop> message_loop_;
- std::unique_ptr<BrowserThreadImpl> ui_thread_;
- std::unique_ptr<BrowserThreadImpl> io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<MockFrameObserver> frame_observer_;
WrappedDeviceFactory* video_capture_device_factory_;
StreamDeviceInfoArray devices_;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
new file mode 100644
index 00000000000..71a0a7e893d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -0,0 +1,367 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/location.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 "build/build_config.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/media/media_stream_requester.h"
+#include "content/browser/renderer_host/media/video_capture_host.h"
+#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/common/media/media_devices.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/base/media_switches.h"
+#include "media/capture/video_capture_types.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
+namespace content {
+
+namespace {
+
+void VideoInputDevicesEnumerated(base::Closure quit_closure,
+ const std::string& salt,
+ const url::Origin& security_origin,
+ MediaDeviceInfoArray* out,
+ const MediaDeviceEnumeration& enumeration) {
+ for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
+ std::string device_id = MediaStreamManager::GetHMACForMediaDeviceID(
+ salt, security_origin, info.device_id);
+ out->push_back(MediaDeviceInfo(device_id, info.label, std::string()));
+ }
+ quit_closure.Run();
+}
+
+} // namespace
+
+// Id used to identify the capture session between renderer and
+// video_capture_host. This is an arbitrary value.
+static const int kDeviceId = 555;
+
+class MockMediaStreamRequester : public MediaStreamRequester {
+ public:
+ MockMediaStreamRequester() {}
+ virtual ~MockMediaStreamRequester() {}
+
+ // MediaStreamRequester implementation.
+ MOCK_METHOD5(StreamGenerated,
+ void(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_devices,
+ const StreamDeviceInfoArray& video_devices));
+ MOCK_METHOD3(StreamGenerationFailed,
+ void(int render_frame_id,
+ int page_request_id,
+ content::MediaStreamRequestResult result));
+ MOCK_METHOD3(DeviceStopped, void(int render_frame_id,
+ const std::string& label,
+ const StreamDeviceInfo& device));
+ MOCK_METHOD4(DevicesEnumerated, void(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& devices));
+ MOCK_METHOD4(DeviceOpened, void(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device_info));
+ MOCK_METHOD1(DevicesChanged, void(MediaStreamType type));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
+};
+
+ACTION_P2(ExitMessageLoop, task_runner, quit_closure) {
+ task_runner->PostTask(FROM_HERE, quit_closure);
+}
+
+// This is an integration test of VideoCaptureHost in conjunction with
+// MediaStreamManager, VideoCaptureManager, VideoCaptureController, and
+// VideoCaptureDevice.
+class VideoCaptureTest : public testing::Test,
+ public mojom::VideoCaptureObserver {
+ public:
+ VideoCaptureTest()
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ audio_manager_(
+ new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get())),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ opened_session_id_(kInvalidMediaCaptureSessionId),
+ observer_binding_(this) {}
+
+ void SetUp() override {
+ SetBrowserClientForTesting(&browser_client_);
+
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kUseFakeDeviceForMediaStream);
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kUseFakeUIForMediaStream);
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
+
+ // Create a Host and connect it to a simulated IPC channel.
+ host_.reset(new VideoCaptureHost(media_stream_manager_.get()));
+
+ OpenSession();
+ }
+
+ void TearDown() override {
+ Mock::VerifyAndClearExpectations(host_.get());
+ EXPECT_TRUE(host_->controllers_.empty());
+
+ CloseSession();
+
+ // Release the reference to the mock object. The object will be destructed
+ // on the current message loop.
+ host_ = nullptr;
+ }
+
+ void OpenSession() {
+ const int render_process_id = 1;
+ const int render_frame_id = 1;
+ const int page_request_id = 1;
+ const url::Origin security_origin(GURL("http://test.com"));
+
+ ASSERT_TRUE(opened_device_label_.empty());
+
+ // Enumerate video devices.
+ MediaDeviceInfoArray video_devices;
+ {
+ base::RunLoop run_loop;
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+ media_stream_manager_->media_devices_manager()->EnumerateDevices(
+ devices_to_enumerate,
+ base::Bind(
+ &VideoInputDevicesEnumerated, run_loop.QuitClosure(),
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ security_origin, &video_devices));
+ run_loop.Run();
+ }
+ ASSERT_FALSE(video_devices.empty());
+
+ // Open the first device.
+ {
+ base::RunLoop run_loop;
+ StreamDeviceInfo opened_device;
+ media_stream_manager_->OpenDevice(
+ &stream_requester_, render_process_id, render_frame_id,
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ page_request_id, video_devices[0].device_id,
+ MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
+ EXPECT_CALL(stream_requester_,
+ DeviceOpened(render_frame_id, page_request_id, _, _))
+ .Times(1)
+ .WillOnce(DoAll(ExitMessageLoop(task_runner_, run_loop.QuitClosure()),
+ SaveArg<2>(&opened_device_label_),
+ SaveArg<3>(&opened_device)));
+ run_loop.Run();
+ Mock::VerifyAndClearExpectations(&stream_requester_);
+ ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id);
+ opened_session_id_ = opened_device.session_id;
+ }
+ }
+
+ void CloseSession() {
+ if (opened_device_label_.empty())
+ return;
+ media_stream_manager_->CancelRequest(opened_device_label_);
+ opened_device_label_.clear();
+ opened_session_id_ = kInvalidMediaCaptureSessionId;
+ }
+
+ protected:
+ // mojom::VideoCaptureObserver implementation.
+ MOCK_METHOD1(OnStateChanged, void(mojom::VideoCaptureState));
+ void OnBufferCreated(int32_t buffer_id,
+ mojo::ScopedSharedBufferHandle handle) override {
+ DoOnBufferCreated(buffer_id);
+ }
+ MOCK_METHOD1(DoOnBufferCreated, void(int32_t));
+ void OnBufferReady(int32_t buffer_id,
+ mojom::VideoFrameInfoPtr info) override {
+ DoOnBufferReady(buffer_id);
+ }
+ MOCK_METHOD1(DoOnBufferReady, void(int32_t));
+ MOCK_METHOD1(OnBufferDestroyed, void(int32_t));
+
+ void StartCapture() {
+ base::RunLoop run_loop;
+ media::VideoCaptureParams params;
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED));
+ EXPECT_CALL(*this, DoOnBufferCreated(_))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return());
+ EXPECT_CALL(*this, DoOnBufferReady(_))
+ .Times(AnyNumber())
+ .WillRepeatedly(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
+
+ host_->Start(kDeviceId, opened_session_id_, params,
+ observer_binding_.CreateInterfacePtrAndBind());
+
+ run_loop.Run();
+ }
+
+ void StartAndImmediateStopCapture() {
+ // Quickly start and then stop capture, without giving much chance for
+ // asynchronous capture operations to produce frames.
+ InSequence s;
+ base::RunLoop run_loop;
+
+ media::VideoCaptureParams params;
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED));
+ host_->Start(kDeviceId, opened_session_id_, params,
+ observer_binding_.CreateInterfacePtrAndBind());
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED));
+ host_->Stop(kDeviceId);
+ run_loop.RunUntilIdle();
+ }
+
+ void PauseResumeCapture() {
+ InSequence s;
+ base::RunLoop run_loop;
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::PAUSED));
+ host_->Pause(kDeviceId);
+
+ media::VideoCaptureParams params;
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::RESUMED));
+ host_->Resume(kDeviceId, opened_session_id_, params);
+ run_loop.RunUntilIdle();
+ }
+
+ void StopCapture() {
+ base::RunLoop run_loop;
+
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED))
+ .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
+ host_->Stop(kDeviceId);
+
+ run_loop.Run();
+
+ EXPECT_TRUE(host_->controllers_.empty());
+ }
+
+ void WaitForOneCapturedBuffer() {
+ base::RunLoop run_loop;
+
+ EXPECT_CALL(*this, DoOnBufferReady(_))
+ .Times(AnyNumber())
+ .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()))
+ .RetiresOnSaturation();
+ run_loop.Run();
+ }
+
+ void SimulateError() {
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::FAILED));
+ VideoCaptureControllerID id(kDeviceId);
+ host_->OnError(id);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ private:
+ // |media_stream_manager_| needs to outlive |thread_bundle_| because it is a
+ // MessageLoop::DestructionObserver.
+ StrictMock<MockMediaStreamRequester> stream_requester_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
+ const content::TestBrowserThreadBundle thread_bundle_;
+ // |audio_manager_| needs to outlive |thread_bundle_| because it uses the
+ // underlying message loop.
+ media::ScopedAudioManagerPtr audio_manager_;
+ content::TestBrowserContext browser_context_;
+ content::TestContentBrowserClient browser_client_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ int opened_session_id_;
+ std::string opened_device_label_;
+
+ std::unique_ptr<VideoCaptureHost> host_;
+ mojo::Binding<mojom::VideoCaptureObserver> observer_binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureTest);
+};
+
+// Construct and destruct all objects. This is a non trivial sequence.
+TEST_F(VideoCaptureTest, ConstructAndDestruct) {}
+
+TEST_F(VideoCaptureTest, StartAndImmediateStop) {
+ StartAndImmediateStopCapture();
+}
+
+TEST_F(VideoCaptureTest, StartAndCaptureAndStop) {
+ StartCapture();
+ WaitForOneCapturedBuffer();
+ WaitForOneCapturedBuffer();
+ StopCapture();
+}
+
+TEST_F(VideoCaptureTest, StartAndErrorAndStop) {
+ StartCapture();
+ SimulateError();
+ StopCapture();
+}
+
+TEST_F(VideoCaptureTest, StartAndCaptureAndError) {
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED))
+ .Times(0);
+ StartCapture();
+ WaitForOneCapturedBuffer();
+ SimulateError();
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+}
+
+TEST_F(VideoCaptureTest, StartAndPauseAndResumeAndStop) {
+ StartCapture();
+ PauseResumeCapture();
+ StopCapture();
+}
+
+TEST_F(VideoCaptureTest, CloseSessionWithoutStopping) {
+ StartCapture();
+
+ // When the session is closed via the stream without stopping capture, the
+ // ENDED event is sent.
+ EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::ENDED));
+ CloseSession();
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc b/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
index 98b4eeb046f..0c4d066e378 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
@@ -14,20 +14,24 @@ namespace content {
OffscreenCanvasCompositorFrameSink::OffscreenCanvasCompositorFrameSink(
const cc::SurfaceId& surface_id,
cc::mojom::MojoCompositorFrameSinkClientPtr client)
- : surface_id_(surface_id), client_(std::move(client)) {}
+ : surface_id_(surface_id), client_(std::move(client)) {
+ cc::SurfaceManager* manager = GetSurfaceManager();
+ surface_factory_ = base::MakeUnique<cc::SurfaceFactory>(
+ surface_id_.frame_sink_id(), manager, this);
+ manager->RegisterFrameSinkId(surface_id_.frame_sink_id());
+ surface_factory_->Create(surface_id_.local_frame_id());
+}
OffscreenCanvasCompositorFrameSink::~OffscreenCanvasCompositorFrameSink() {
- if (surface_factory_) {
- cc::SurfaceManager* manager = GetSurfaceManager();
- if (!manager) {
- // Inform SurfaceFactory that SurfaceManager's no longer alive to
- // avoid its destruction error.
- surface_factory_->DidDestroySurfaceManager();
- } else {
- manager->InvalidateFrameSinkId(surface_id_.frame_sink_id());
- }
- surface_factory_->Destroy(surface_id_.local_frame_id());
+ cc::SurfaceManager* manager = GetSurfaceManager();
+ if (!manager) {
+ // Inform SurfaceFactory that SurfaceManager's no longer alive to
+ // avoid its destruction error.
+ surface_factory_->DidDestroySurfaceManager();
+ } else {
+ manager->InvalidateFrameSinkId(surface_id_.frame_sink_id());
}
+ surface_factory_->Destroy(surface_id_.local_frame_id());
}
// static
@@ -41,18 +45,13 @@ void OffscreenCanvasCompositorFrameSink::Create(
}
void OffscreenCanvasCompositorFrameSink::SubmitCompositorFrame(
- cc::CompositorFrame frame,
- const SubmitCompositorFrameCallback& callback) {
- if (!surface_factory_) {
- cc::SurfaceManager* manager = GetSurfaceManager();
- surface_factory_ = base::MakeUnique<cc::SurfaceFactory>(
- surface_id_.frame_sink_id(), manager, this);
- surface_factory_->Create(surface_id_.local_frame_id());
-
- manager->RegisterFrameSinkId(surface_id_.frame_sink_id());
- }
- surface_factory_->SubmitCompositorFrame(surface_id_.local_frame_id(),
- std::move(frame), callback);
+ cc::CompositorFrame frame) {
+ ++ack_pending_count_;
+ surface_factory_->SubmitCompositorFrame(
+ surface_id_.local_frame_id(), std::move(frame),
+ base::Bind(
+ &OffscreenCanvasCompositorFrameSink::DidReceiveCompositorFrameAck,
+ base::Unretained(this)));
}
void OffscreenCanvasCompositorFrameSink::SetNeedsBeginFrame(
@@ -62,7 +61,16 @@ void OffscreenCanvasCompositorFrameSink::SetNeedsBeginFrame(
void OffscreenCanvasCompositorFrameSink::ReturnResources(
const cc::ReturnedResourceArray& resources) {
- client_->ReturnResources(resources);
+ if (resources.empty())
+ return;
+
+ if (!ack_pending_count_ && client_) {
+ client_->ReclaimResources(resources);
+ return;
+ }
+
+ std::copy(resources.begin(), resources.end(),
+ std::back_inserter(surface_returned_resources_));
}
void OffscreenCanvasCompositorFrameSink::WillDrawSurface(
@@ -72,4 +80,16 @@ void OffscreenCanvasCompositorFrameSink::WillDrawSurface(
void OffscreenCanvasCompositorFrameSink::SetBeginFrameSource(
cc::BeginFrameSource* begin_frame_source) {}
+void OffscreenCanvasCompositorFrameSink::DidReceiveCompositorFrameAck() {
+ if (!client_)
+ return;
+ client_->DidReceiveCompositorFrameAck();
+ DCHECK_GT(ack_pending_count_, 0);
+ if (!surface_returned_resources_.empty()) {
+ client_->ReclaimResources(surface_returned_resources_);
+ surface_returned_resources_.clear();
+ }
+ ack_pending_count_--;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h b/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
index 20508d89016..0d838ed11ee 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
@@ -25,9 +25,7 @@ class OffscreenCanvasCompositorFrameSink
cc::mojom::MojoCompositorFrameSinkRequest request);
// cc::mojom::MojoCompositorFrameSink implementation.
- void SubmitCompositorFrame(
- cc::CompositorFrame frame,
- const SubmitCompositorFrameCallback& callback) override;
+ void SubmitCompositorFrame(cc::CompositorFrame frame) override;
void SetNeedsBeginFrame(bool needs_begin_frame) override;
// cc::SurfaceFactoryClient implementation.
@@ -37,9 +35,13 @@ class OffscreenCanvasCompositorFrameSink
void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
private:
+ void DidReceiveCompositorFrameAck();
+
cc::SurfaceId surface_id_;
std::unique_ptr<cc::SurfaceFactory> surface_factory_;
cc::mojom::MojoCompositorFrameSinkClientPtr client_;
+ int ack_pending_count_ = 0;
+ cc::ReturnedResourceArray surface_returned_resources_;
DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasCompositorFrameSink);
};
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 bac06970c23..75a04d626a3 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -8,6 +8,7 @@
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_manager.h"
#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_manager.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -16,7 +17,12 @@ namespace content {
OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl()
: id_allocator_(new cc::SurfaceIdAllocator()) {}
-OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {}
+OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
+ if (frame_sink_id_.is_valid()) {
+ OffscreenCanvasSurfaceManager::GetInstance()
+ ->UnregisterOffscreenCanvasSurfaceInstance(frame_sink_id_);
+ }
+}
// static
void OffscreenCanvasSurfaceImpl::Create(
@@ -28,11 +34,27 @@ void OffscreenCanvasSurfaceImpl::Create(
void OffscreenCanvasSurfaceImpl::GetSurfaceId(
const GetSurfaceIdCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (frame_sink_id_.is_valid()) {
+ // This IPC should be only called once for each HTMLCanvasElement. In this
+ // case, frame_sink_id_ is still unset.
+ // As the browser makes no assumption of correct behavior of renderer, in
+ // an unwanted situation when this function is invoked twice, we need to
+ // unregister the instance from manager.
+ OffscreenCanvasSurfaceManager::GetInstance()
+ ->UnregisterOffscreenCanvasSurfaceInstance(frame_sink_id_);
+ mojo::ReportBadMessage(
+ "The same OffscreenCanvasSurfaceImpl is registered to "
+ "OffscreenCanvasSurfaceManager twice.");
+ }
+
+ frame_sink_id_ = AllocateFrameSinkId();
+ cc::SurfaceId surface_id =
+ cc::SurfaceId(frame_sink_id_, id_allocator_->GenerateId());
- cc::LocalFrameId local_frame_id = id_allocator_->GenerateId();
- surface_id_ = cc::SurfaceId(AllocateFrameSinkId(), local_frame_id);
+ OffscreenCanvasSurfaceManager::GetInstance()
+ ->RegisterOffscreenCanvasSurfaceInstance(frame_sink_id_, this);
- callback.Run(surface_id_);
+ callback.Run(surface_id);
}
void OffscreenCanvasSurfaceImpl::Require(const cc::SurfaceId& surface_id,
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 6ab9214688f..ad14ad40829 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
@@ -13,7 +13,8 @@
namespace content {
-class OffscreenCanvasSurfaceImpl : public blink::mojom::OffscreenCanvasSurface {
+class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
+ : public blink::mojom::OffscreenCanvasSurface {
public:
OffscreenCanvasSurfaceImpl();
~OffscreenCanvasSurfaceImpl() override;
@@ -26,10 +27,12 @@ class OffscreenCanvasSurfaceImpl : public blink::mojom::OffscreenCanvasSurface {
const cc::SurfaceSequence& sequence) override;
void Satisfy(const cc::SurfaceSequence& sequence) override;
+ const cc::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
+
private:
// Surface-related state
std::unique_ptr<cc::SurfaceIdAllocator> id_allocator_;
- cc::SurfaceId surface_id_;
+ cc::FrameSinkId frame_sink_id_;
DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceImpl);
};
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.cc b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.cc
new file mode 100644
index 00000000000..bf7fecb0363
--- /dev/null
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.cc
@@ -0,0 +1,53 @@
+// 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 "base/lazy_instance.h"
+#include "cc/surfaces/surface_manager.h"
+#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_manager.h"
+
+namespace content {
+
+namespace {
+base::LazyInstance<OffscreenCanvasSurfaceManager>::Leaky g_manager =
+ LAZY_INSTANCE_INITIALIZER;
+}
+
+OffscreenCanvasSurfaceManager::OffscreenCanvasSurfaceManager() {
+ GetSurfaceManager()->AddObserver(this);
+}
+
+OffscreenCanvasSurfaceManager::~OffscreenCanvasSurfaceManager() {
+ registered_surface_instances_.clear();
+ GetSurfaceManager()->RemoveObserver(this);
+}
+
+OffscreenCanvasSurfaceManager* OffscreenCanvasSurfaceManager::GetInstance() {
+ return g_manager.Pointer();
+}
+
+void OffscreenCanvasSurfaceManager::RegisterOffscreenCanvasSurfaceInstance(
+ cc::FrameSinkId frame_sink_id,
+ OffscreenCanvasSurfaceImpl* surface_instance) {
+ DCHECK(surface_instance);
+ DCHECK_EQ(registered_surface_instances_.count(frame_sink_id), 0u);
+ registered_surface_instances_[frame_sink_id] = surface_instance;
+}
+
+void OffscreenCanvasSurfaceManager::UnregisterOffscreenCanvasSurfaceInstance(
+ cc::FrameSinkId frame_sink_id) {
+ DCHECK_EQ(registered_surface_instances_.count(frame_sink_id), 1u);
+ registered_surface_instances_.erase(frame_sink_id);
+}
+
+OffscreenCanvasSurfaceImpl* OffscreenCanvasSurfaceManager::GetSurfaceInstance(
+ cc::FrameSinkId frame_sink_id) {
+ auto search = registered_surface_instances_.find(frame_sink_id);
+ if (search != registered_surface_instances_.end()) {
+ return search->second;
+ }
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.h b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.h
new file mode 100644
index 00000000000..3901bb4e712
--- /dev/null
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_MANAGER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_MANAGER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_observer.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+
+namespace content {
+
+class CONTENT_EXPORT OffscreenCanvasSurfaceManager
+ : public cc::SurfaceObserver {
+ public:
+ OffscreenCanvasSurfaceManager();
+ virtual ~OffscreenCanvasSurfaceManager();
+
+ static OffscreenCanvasSurfaceManager* GetInstance();
+
+ void RegisterOffscreenCanvasSurfaceInstance(cc::FrameSinkId,
+ OffscreenCanvasSurfaceImpl*);
+ void UnregisterOffscreenCanvasSurfaceInstance(cc::FrameSinkId);
+ OffscreenCanvasSurfaceImpl* GetSurfaceInstance(cc::FrameSinkId);
+
+ private:
+ friend class OffscreenCanvasSurfaceManagerTest;
+
+ // cc::SurfaceObserver implementation.
+ // TODO(crbug.com/662498): Implement these functions when
+ // OffscreenCanvasSurfaceManager must propagate the resizing information
+ // back to renderer/main.
+ void OnSurfaceCreated(const cc::SurfaceId& surface_id,
+ const gfx::Size& frame_size,
+ float device_scale_factor) override {}
+ void OnSurfaceDamaged(const cc::SurfaceId&, bool* changed) override {}
+
+ // When an OffscreenCanvasSurfaceImpl instance is destructed, it will
+ // unregister the corresponding entry from this map.
+ std::unordered_map<cc::FrameSinkId,
+ OffscreenCanvasSurfaceImpl*,
+ cc::FrameSinkIdHash>
+ registered_surface_instances_;
+ DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc
new file mode 100644
index 00000000000..ef85a713fa4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 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/compositor/test/no_transport_image_transport_factory.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_manager.h"
+#include "content/public/test/test_browser_thread.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
+#include "content/test/mock_gpu_channel_establish_factory.h"
+#else
+#include "content/browser/compositor/image_transport_factory.h"
+#endif
+
+namespace content {
+
+class OffscreenCanvasSurfaceManagerTest : public testing::Test {
+ public:
+ int getNumSurfaceImplInstances() {
+ return OffscreenCanvasSurfaceManager::GetInstance()
+ ->registered_surface_instances_.size();
+ }
+ const cc::SurfaceId& getCurrentSurfaceId() const {
+ return current_surface_id_;
+ }
+ void setSurfaceId(const cc::SurfaceId& surface_id) {
+ current_surface_id_ = surface_id;
+ }
+
+ protected:
+ void SetUp() override;
+ void TearDown() override;
+
+ private:
+ cc::SurfaceId current_surface_id_;
+ std::unique_ptr<TestBrowserThread> ui_thread_;
+ base::MessageLoopForUI message_loop_;
+#if defined(OS_ANDROID)
+ MockGpuChannelEstablishFactory gpu_channel_factory_;
+#endif
+};
+
+void OffscreenCanvasSurfaceManagerTest::SetUp() {
+#if defined(OS_ANDROID)
+ ContextProviderFactoryImpl::Initialize(&gpu_channel_factory_);
+ ui::ContextProviderFactory::SetInstance(
+ ContextProviderFactoryImpl::GetInstance());
+#else
+ ImageTransportFactory::InitializeForUnitTests(
+ std::unique_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
+#endif
+ ui_thread_.reset(new TestBrowserThread(BrowserThread::UI, &message_loop_));
+}
+
+void OffscreenCanvasSurfaceManagerTest::TearDown() {
+#if defined(OS_ANDROID)
+ ui::ContextProviderFactory::SetInstance(nullptr);
+ ContextProviderFactoryImpl::Terminate();
+#else
+ ImageTransportFactory::Terminate();
+#endif
+}
+
+// This test mimics the workflow of OffscreenCanvas.commit() on renderer
+// process.
+TEST_F(OffscreenCanvasSurfaceManagerTest,
+ SingleHTMLCanvasElementTransferToOffscreen) {
+ // Assume that HTMLCanvasElement.transferControlToOffscreen() is triggered and
+ // it will invoke GetSurfaceId function on OffscreenCanvasSurfaceImpl to
+ // obtain a unique SurfaceId from browser.
+ auto surface_impl = base::WrapUnique(new OffscreenCanvasSurfaceImpl());
+ surface_impl->GetSurfaceId(
+ base::Bind(&OffscreenCanvasSurfaceManagerTest::setSurfaceId,
+ base::Unretained(this)));
+
+ EXPECT_TRUE(this->getCurrentSurfaceId().is_valid());
+ EXPECT_EQ(1, this->getNumSurfaceImplInstances());
+ cc::FrameSinkId frame_sink_id = surface_impl.get()->frame_sink_id();
+ EXPECT_EQ(frame_sink_id, this->getCurrentSurfaceId().frame_sink_id());
+ EXPECT_EQ(surface_impl.get(),
+ OffscreenCanvasSurfaceManager::GetInstance()->GetSurfaceInstance(
+ frame_sink_id));
+
+ surface_impl = nullptr;
+ EXPECT_EQ(0, this->getNumSurfaceImplInstances());
+}
+
+TEST_F(OffscreenCanvasSurfaceManagerTest,
+ MultiHTMLCanvasElementTransferToOffscreen) {
+ // Same scenario as above test except that now we have two HTMLCanvasElement
+ // transferControlToOffscreen at the same time.
+ auto surface_impl_a = base::WrapUnique(new OffscreenCanvasSurfaceImpl());
+ surface_impl_a->GetSurfaceId(
+ base::Bind(&OffscreenCanvasSurfaceManagerTest::setSurfaceId,
+ base::Unretained(this)));
+ cc::SurfaceId surface_id_a = this->getCurrentSurfaceId();
+
+ EXPECT_TRUE(surface_id_a.is_valid());
+
+ auto surface_impl_b = base::WrapUnique(new OffscreenCanvasSurfaceImpl());
+ surface_impl_b->GetSurfaceId(
+ base::Bind(&OffscreenCanvasSurfaceManagerTest::setSurfaceId,
+ base::Unretained(this)));
+ cc::SurfaceId surface_id_b = this->getCurrentSurfaceId();
+
+ EXPECT_TRUE(surface_id_b.is_valid());
+ EXPECT_NE(surface_id_a, surface_id_b);
+
+ EXPECT_EQ(2, this->getNumSurfaceImplInstances());
+ EXPECT_EQ(surface_impl_a.get(),
+ OffscreenCanvasSurfaceManager::GetInstance()->GetSurfaceInstance(
+ surface_id_a.frame_sink_id()));
+ EXPECT_EQ(surface_impl_b.get(),
+ OffscreenCanvasSurfaceManager::GetInstance()->GetSurfaceInstance(
+ surface_id_b.frame_sink_id()));
+
+ surface_impl_a = nullptr;
+ EXPECT_EQ(1, this->getNumSurfaceImplInstances());
+ surface_impl_b = nullptr;
+ EXPECT_EQ(0, this->getNumSurfaceImplInstances());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index f8163433f8d..62eca7e6deb 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -7,11 +7,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace ui {
-class LatencyInfo;
-}
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index c9ead39b0d2..b3de3e5a432 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -24,7 +24,7 @@
#include "net/log/net_log_source.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/client_socket_factory.h"
-#include "net/udp/datagram_client_socket.h"
+#include "net/socket/datagram_client_socket.h"
#include "net/url_request/url_request_context_getter.h"
using content::BrowserMessageFilter;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index b99476d0a77..a1a50c42dbf 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -16,7 +16,7 @@
#include "content/common/p2p_socket_type.h"
#include "content/public/browser/render_process_host.h"
#include "net/base/ip_endpoint.h"
-#include "net/udp/datagram_socket.h"
+#include "net/socket/datagram_socket.h"
namespace IPC {
class Sender;
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 252026400e0..039c619ccf4 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -10,6 +10,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/sys_byteorder.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/common/p2p_messages.h"
#include "ipc/ipc_sender.h"
#include "jingle/glue/fake_ssl_client_socket.h"
@@ -122,9 +123,7 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
// directly here as the caller may not expect an error/close to
// happen here. This is okay, as from the caller's point of view,
// the connect always happens asynchronously.
- base::MessageLoop* message_loop = base::MessageLoop::current();
- CHECK(message_loop);
- message_loop->task_runner()->PostTask(
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&P2PSocketHostTcpBase::OnConnected,
base::Unretained(this), status));
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
index 4865d5b3d6b..a7771c9871e 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -14,7 +14,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/common/p2p_socket_type.h"
#include "net/base/completion_callback.h"
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
index 01858d396e4..57a539b4557 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -22,8 +22,8 @@
#include "content/common/content_export.h"
#include "content/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
-#include "net/udp/diff_serv_code_point.h"
-#include "net/udp/udp_server_socket.h"
+#include "net/socket/diff_serv_code_point.h"
+#include "net/socket/udp_server_socket.h"
#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
index af37bc33f00..1ac1f9d7764 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
@@ -18,7 +18,7 @@
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_with_source.h"
-#include "net/udp/datagram_server_socket.h"
+#include "net/socket/datagram_server_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index f1b4897307f..1929907b83e 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -5,7 +5,7 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "base/memory/ptr_util.h"
-#include "base/metrics/sparse_histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/common/pepper_renderer_instance_data.h"
@@ -71,8 +71,8 @@ BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
// Notify instance observers about our impending destruction.
for (auto& instance_data : instance_map_) {
- FOR_EACH_OBSERVER(InstanceObserver, instance_data.second->observer_list,
- OnHostDestroyed());
+ for (auto& observer : instance_data.second->observer_list)
+ observer.OnHostDestroyed();
}
// Delete the host explicitly first. This shutdown will destroy the
@@ -180,8 +180,8 @@ void BrowserPpapiHostImpl::OnThrottleStateChanged(PP_Instance instance,
auto* data = instance_map_.get(instance);
if (data) {
data->is_throttled = is_throttled;
- FOR_EACH_OBSERVER(InstanceObserver, data->observer_list,
- OnThrottleStateChanged(is_throttled));
+ for (auto& observer : data->observer_list)
+ observer.OnThrottleStateChanged(is_throttled);
}
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
index 8e2d7fa4832..f18aa82ecec 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
@@ -8,8 +8,9 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "ppapi/c/pp_errors.h"
+#include "printing/features/features.h"
-#if defined(ENABLE_PRINT_PREVIEW)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
#include "printing/printing_context.h" // nogncheck
#include "printing/units.h" // nogncheck
#endif
@@ -18,7 +19,7 @@ namespace content {
namespace {
-#if defined(ENABLE_PRINT_PREVIEW)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Print units conversion functions.
int32_t DeviceUnitsInPoints(int32_t device_units,
int32_t device_units_per_inch) {
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 00b4a7abf56..54a89249ee2 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -14,8 +14,6 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
-class GURL;
-
namespace ppapi {
namespace proxy {
class ResourceMessageCallParams;
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 0c0b48d86c2..132a45880bf 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
@@ -22,7 +22,7 @@
#include "net/base/net_errors.h"
#include "net/base/rand_callback.h"
#include "net/log/net_log_source.h"
-#include "net/udp/udp_socket.h"
+#include "net/socket/udp_socket.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
index aef6c2fa144..0c5bbca94fb 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
@@ -21,7 +21,7 @@
#include "net/base/completion_callback.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
-#include "net/udp/udp_socket.h"
+#include "net/socket/udp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/ppb_udp_socket.h"
@@ -51,7 +51,6 @@ struct ReplyMessageContext;
namespace content {
class BrowserPpapiHostImpl;
-struct SocketPermissionRequest;
class CONTENT_EXPORT PepperUDPSocketMessageFilter
: public ppapi::host::ResourceMessageFilter {
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 93f4ebd1736..ca456956284 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -70,6 +70,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "url/gurl.h"
+#include "url/origin.h"
#if defined(OS_MACOSX)
#include "content/common/mac/font_descriptor.h"
@@ -161,16 +162,13 @@ RenderMessageFilter::~RenderMessageFilter() {
BrowserGpuMemoryBufferManager::current();
if (gpu_memory_buffer_manager)
gpu_memory_buffer_manager->ProcessRemoved(PeerHandle(), render_process_id_);
- HostDiscardableSharedMemoryManager::current()->ProcessRemoved(
+ discardable_memory::DiscardableSharedMemoryManager::current()->ClientRemoved(
render_process_id_);
}
bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
- IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
- IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
- OnCreateFullscreenWidget)
#if defined(OS_MACOSX)
// On Mac, the IPCs ViewHostMsg_SwapCompositorFrame, ViewHostMsg_UpdateRect,
// and GpuCommandBufferMsg_SwapBuffersCompleted need to be handled in a
@@ -185,11 +183,9 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
ViewHostMsg_SetNeedsBeginFrames,
ResizeHelperPostMsgToUIThread(render_process_id_, message))
#endif
- // NB: The SyncAllocateSharedMemory, SyncAllocateGpuMemoryBuffer, and
- // DeletedGpuMemoryBuffer IPCs are handled here for renderer processes. For
- // non-renderer child processes, they are handled in ChildProcessHostImpl.
- IPC_MESSAGE_HANDLER_DELAY_REPLY(
- ChildProcessHostMsg_SyncAllocateSharedMemory, OnAllocateSharedMemory)
+ // NB: The SyncAllocateGpuMemoryBuffer and DeletedGpuMemoryBuffer IPCs are
+ // handled here for renderer processes. For non-renderer child processes,
+ // they are handled in ChildProcessHostImpl.
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateSharedBitmap, OnAllocateSharedBitmap)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
@@ -241,17 +237,6 @@ void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
*thread = BrowserThread::UI;
}
-void RenderMessageFilter::OnCreateWidget(int opener_id,
- blink::WebPopupType popup_type,
- int* route_id) {
- render_widget_helper_->CreateNewWidget(opener_id, popup_type, route_id);
-}
-
-void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
- int* route_id) {
- render_widget_helper_->CreateNewFullscreenWidget(opener_id, route_id);
-}
-
void RenderMessageFilter::GenerateRoutingID(
const GenerateRoutingIDCallback& callback) {
callback.Run(render_widget_helper_->GetNextRoutingID());
@@ -302,6 +287,23 @@ void RenderMessageFilter::CreateNewWindow(
callback.Run(std::move(reply));
}
+void RenderMessageFilter::CreateNewWidget(
+ int32_t opener_id,
+ blink::WebPopupType popup_type,
+ const CreateNewWidgetCallback& callback) {
+ int route_id = MSG_ROUTING_NONE;
+ render_widget_helper_->CreateNewWidget(opener_id, popup_type, &route_id);
+ callback.Run(route_id);
+}
+
+void RenderMessageFilter::CreateFullscreenWidget(
+ int opener_id,
+ const CreateFullscreenWidgetCallback& callback) {
+ int route_id = 0;
+ render_widget_helper_->CreateNewFullscreenWidget(opener_id, &route_id);
+ callback.Run(route_id);
+}
+
#if defined(OS_MACOSX)
void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
@@ -332,25 +334,6 @@ void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
#endif // defined(OS_MACOSX)
-void RenderMessageFilter::AllocateSharedMemoryOnFileThread(
- uint32_t buffer_size,
- IPC::Message* reply_msg) {
- base::SharedMemoryHandle handle;
- ChildProcessHostImpl::AllocateSharedMemory(buffer_size, PeerHandle(),
- &handle);
- ChildProcessHostMsg_SyncAllocateSharedMemory::WriteReplyParams(reply_msg,
- handle);
- Send(reply_msg);
-}
-
-void RenderMessageFilter::OnAllocateSharedMemory(uint32_t buffer_size,
- IPC::Message* reply_msg) {
- BrowserThread::PostTask(
- BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
- base::Bind(&RenderMessageFilter::AllocateSharedMemoryOnFileThread, this,
- buffer_size, reply_msg));
-}
-
void RenderMessageFilter::AllocateSharedBitmapOnFileThread(
uint32_t buffer_size,
const cc::SharedBitmapId& id,
@@ -389,11 +372,11 @@ void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
void RenderMessageFilter::AllocateLockedDiscardableSharedMemoryOnFileThread(
uint32_t size,
- DiscardableSharedMemoryId id,
+ discardable_memory::DiscardableSharedMemoryId id,
IPC::Message* reply_msg) {
base::SharedMemoryHandle handle;
- HostDiscardableSharedMemoryManager::current()
- ->AllocateLockedDiscardableSharedMemoryForChild(
+ discardable_memory::DiscardableSharedMemoryManager::current()
+ ->AllocateLockedDiscardableSharedMemoryForClient(
PeerHandle(), render_process_id_, size, id, &handle);
ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory::
WriteReplyParams(reply_msg, handle);
@@ -402,7 +385,7 @@ void RenderMessageFilter::AllocateLockedDiscardableSharedMemoryOnFileThread(
void RenderMessageFilter::OnAllocateLockedDiscardableSharedMemory(
uint32_t size,
- DiscardableSharedMemoryId id,
+ discardable_memory::DiscardableSharedMemoryId id,
IPC::Message* reply_msg) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
@@ -412,13 +395,13 @@ void RenderMessageFilter::OnAllocateLockedDiscardableSharedMemory(
}
void RenderMessageFilter::DeletedDiscardableSharedMemoryOnFileThread(
- DiscardableSharedMemoryId id) {
- HostDiscardableSharedMemoryManager::current()
- ->ChildDeletedDiscardableSharedMemory(id, render_process_id_);
+ discardable_memory::DiscardableSharedMemoryId id) {
+ discardable_memory::DiscardableSharedMemoryManager::current()
+ ->ClientDeletedDiscardableSharedMemory(id, render_process_id_);
}
void RenderMessageFilter::OnDeletedDiscardableSharedMemory(
- DiscardableSharedMemoryId id) {
+ discardable_memory::DiscardableSharedMemoryId id) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
base::Bind(
@@ -488,7 +471,7 @@ void RenderMessageFilter::OnCacheableMetadataAvailableForCacheStorage(
memcpy(buf->data(), &data.front(), data.size());
cache_storage_context_->cache_manager()->OpenCache(
- GURL(cache_storage_origin.Serialize()), cache_storage_cache_name,
+ cache_storage_origin.GetURL(), cache_storage_cache_name,
base::Bind(&RenderMessageFilter::OnCacheStorageOpenCallback,
weak_ptr_factory_.GetWeakPtr(), url, expected_response_time,
buf, data.size()));
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index 83afa13008c..99fcd059a1c 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -14,15 +14,14 @@
#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "cc/resources/shared_bitmap_manager.h"
+#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
#include "content/common/cache_storage/cache_storage_types.h"
-#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/public/browser/browser_associated_interface.h"
@@ -51,9 +50,7 @@ class GURL;
struct FontDescriptor;
namespace base {
-class ProcessMetrics;
class SharedMemory;
-class TaskRunner;
}
namespace gfx {
@@ -121,10 +118,6 @@ class CONTENT_EXPORT RenderMessageFilter
friend class base::DeleteHelper<RenderMessageFilter>;
void OnGetProcessMemorySizes(size_t* private_bytes, size_t* shared_bytes);
- void OnCreateWidget(int opener_id,
- blink::WebPopupType popup_type,
- int* route_id);
- void OnCreateFullscreenWidget(int opener_id, int* route_id);
#if defined(OS_MACOSX)
// Messages for OOP font loading.
@@ -136,6 +129,12 @@ class CONTENT_EXPORT RenderMessageFilter
void GenerateRoutingID(const GenerateRoutingIDCallback& routing_id) override;
void CreateNewWindow(mojom::CreateNewWindowParamsPtr params,
const CreateNewWindowCallback& callback) override;
+ void CreateNewWidget(int32_t opener_id,
+ blink::WebPopupType popup_type,
+ const CreateNewWidgetCallback& callback) override;
+ void CreateFullscreenWidget(
+ int opener_id,
+ const CreateFullscreenWidgetCallback& callback) override;
// Message handlers called on the browser IO thread:
void OnEstablishGpuChannel(IPC::Message* reply);
@@ -150,9 +149,6 @@ class CONTENT_EXPORT RenderMessageFilter
// Used to ask the browser to allocate a block of shared memory for the
// renderer to send back data in, since shared memory can't be created
// in the renderer on POSIX due to the sandbox.
- void AllocateSharedMemoryOnFileThread(uint32_t buffer_size,
- IPC::Message* reply_msg);
- void OnAllocateSharedMemory(uint32_t buffer_size, IPC::Message* reply_msg);
void AllocateSharedBitmapOnFileThread(uint32_t buffer_size,
const cc::SharedBitmapId& id,
IPC::Message* reply_msg);
@@ -168,13 +164,16 @@ class CONTENT_EXPORT RenderMessageFilter
// Browser side discardable shared memory allocation.
void AllocateLockedDiscardableSharedMemoryOnFileThread(
uint32_t size,
- DiscardableSharedMemoryId id,
+ discardable_memory::DiscardableSharedMemoryId id,
+ IPC::Message* reply_message);
+ void OnAllocateLockedDiscardableSharedMemory(
+ uint32_t size,
+ discardable_memory::DiscardableSharedMemoryId id,
IPC::Message* reply_message);
- void OnAllocateLockedDiscardableSharedMemory(uint32_t size,
- DiscardableSharedMemoryId id,
- IPC::Message* reply_message);
- void DeletedDiscardableSharedMemoryOnFileThread(DiscardableSharedMemoryId id);
- void OnDeletedDiscardableSharedMemory(DiscardableSharedMemoryId id);
+ void DeletedDiscardableSharedMemoryOnFileThread(
+ discardable_memory::DiscardableSharedMemoryId id);
+ void OnDeletedDiscardableSharedMemory(
+ discardable_memory::DiscardableSharedMemoryId id);
#if defined(OS_LINUX)
void SetThreadPriorityOnFileThread(base::PlatformThreadId ns_tid,
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 01531ecc612..f1b7ec479ef 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -19,8 +19,8 @@
#include "content/public/test/test_service.mojom.h"
#include "content/shell/browser/shell.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
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 f952adcf1ec..001d6d32eda 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -88,6 +88,7 @@
#include "content/browser/mime_registry_impl.h"
#include "content/browser/notifications/notification_message_filter.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/browser/payments/payment_app_manager.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/browser/profiler_message_filter.h"
@@ -158,16 +159,15 @@
#include "content/public/common/resource_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "device/battery/battery_monitor_impl.h"
+#include "device/power_monitor/power_monitor_message_broadcaster.h"
#include "device/time_zone_monitor/time_zone_monitor.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/gpu_switches.h"
-#include "ipc/attachment_broker.h"
-#include "ipc/attachment_broker_privileged.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_mojo.h"
@@ -177,11 +177,12 @@
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
-#include "services/shell/runner/common/switches.h"
+#include "services/service_manager/public/cpp/connection.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
+#include "services/service_manager/runner/common/switches.h"
#include "storage/browser/fileapi/sandbox_file_system_backend.h"
+#include "third_party/WebKit/public/public_features.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
@@ -236,7 +237,7 @@
#include "content/common/media/media_stream_messages.h"
#endif
-#if defined(USE_MINIKIN_HYPHENATION)
+#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
#include "content/browser/hyphenation/hyphenation_impl.h"
#endif
@@ -249,7 +250,6 @@
namespace content {
namespace {
-const char kRendererInterfaceKeyName[] = "mojom_renderer_interface";
const char kSiteProcessMapKeyName[] = "content_site_process_map";
#ifdef ENABLE_WEBRTC
@@ -258,11 +258,13 @@ const base::FilePath::CharType kAecDumpFileNameAddition[] =
#endif
void CacheShaderInfo(int32_t id, base::FilePath path) {
- ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
+ if (ShaderCacheFactory::GetInstance())
+ ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
}
void RemoveShaderInfo(int32_t id) {
- ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
+ if (ShaderCacheFactory::GetInstance())
+ ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
}
net::URLRequestContext* GetRequestContext(
@@ -366,21 +368,6 @@ SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
return map;
}
-// Holds a Mojo associated interface proxy in an RPH's user data.
-template <typename Interface>
-class AssociatedInterfaceHolder : public base::SupportsUserData::Data {
- public:
- AssociatedInterfaceHolder() {}
- ~AssociatedInterfaceHolder() override {}
-
- mojo::AssociatedInterfacePtr<Interface>& proxy() { return proxy_; }
-
- private:
- mojo::AssociatedInterfacePtr<Interface> proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceHolder);
-};
-
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
// This static member variable holds the zygote communication information for
// the renderer.
@@ -391,12 +378,7 @@ ZygoteHandle g_render_zygote;
class RendererSandboxedProcessLauncherDelegate
: public SandboxedProcessLauncherDelegate {
public:
- explicit RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel)
-#if defined(OS_POSIX)
- : ipc_fd_(channel->TakeClientFileDescriptor())
-#endif // OS_POSIX
- {
- }
+ RendererSandboxedProcessLauncherDelegate() {}
~RendererSandboxedProcessLauncherDelegate() override {}
@@ -413,8 +395,7 @@ class RendererSandboxedProcessLauncherDelegate
return GetContentClient()->browser()->PreSpawnRenderer(policy);
}
-#elif defined(OS_POSIX)
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
ZygoteHandle* GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
@@ -424,16 +405,9 @@ class RendererSandboxedProcessLauncherDelegate
return nullptr;
return GetGenericZygote();
}
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
- base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
SandboxType GetSandboxType() override { return SANDBOX_TYPE_RENDERER; }
-
- private:
-#if defined(OS_POSIX)
- base::ScopedFD ipc_fd_;
-#endif // OS_POSIX
};
const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey";
@@ -518,8 +492,8 @@ class RenderProcessHostImpl::ConnectionFilterController
class RenderProcessHostImpl::ConnectionFilterImpl : public ConnectionFilter {
public:
ConnectionFilterImpl(
- const shell::Identity& child_identity,
- std::unique_ptr<shell::InterfaceRegistry> registry)
+ const service_manager::Identity& child_identity,
+ std::unique_ptr<service_manager::InterfaceRegistry> registry)
: child_identity_(child_identity),
registry_(std::move(registry)),
controller_(new ConnectionFilterController(this)),
@@ -546,9 +520,9 @@ class RenderProcessHostImpl::ConnectionFilterImpl : public ConnectionFilter {
private:
// ConnectionFilter:
- bool OnConnect(const shell::Identity& remote_identity,
- shell::InterfaceRegistry* registry,
- shell::Connector* connector) override {
+ bool OnConnect(const service_manager::Identity& remote_identity,
+ service_manager::InterfaceRegistry* registry,
+ service_manager::Connector* connector) override {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// We only fulfill connections from the renderer we host.
@@ -578,7 +552,7 @@ class RenderProcessHostImpl::ConnectionFilterImpl : public ConnectionFilter {
mojo::ScopedMessagePipeHandle handle) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- shell::mojom::InterfaceProvider* provider = registry_.get();
+ service_manager::mojom::InterfaceProvider* provider = registry_.get();
base::AutoLock lock(enabled_lock_);
if (enabled_)
@@ -586,8 +560,8 @@ class RenderProcessHostImpl::ConnectionFilterImpl : public ConnectionFilter {
}
base::ThreadChecker thread_checker_;
- shell::Identity child_identity_;
- std::unique_ptr<shell::InterfaceRegistry> registry_;
+ service_manager::Identity child_identity_;
+ std::unique_ptr<service_manager::InterfaceRegistry> registry_;
scoped_refptr<ConnectionFilterController> controller_;
// Guards |enabled_|.
@@ -683,7 +657,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
is_self_deleted_(false),
#endif
pending_views_(0),
- child_token_(mojo::edk::GenerateRandomToken()),
service_worker_ref_count_(0),
shared_worker_ref_count_(0),
is_worker_ref_count_disabled_(false),
@@ -692,7 +665,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
mojo::BindingSetDispatchMode::WITH_CONTEXT),
visible_widgets_(0),
is_process_backgrounded_(false),
- is_initialized_(false),
id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
browser_context_(browser_context),
storage_partition_impl_(storage_partition_impl),
@@ -702,7 +674,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
gpu_observer_registered_(false),
delayed_cleanup_needed_(false),
within_process_died_observer_(false),
- power_monitor_broadcaster_(this),
#if defined(ENABLE_WEBRTC)
webrtc_eventlog_host_(id_),
#endif
@@ -740,41 +711,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
AddObserver(BootstrapSandboxManager::GetInstance());
#endif
-#if USE_ATTACHMENT_BROKER
- // Construct the privileged attachment broker early in the life cycle of a
- // render process. This ensures that when a test is being run in one of the
- // single process modes, the global attachment broker is the privileged
- // attachment broker, rather than an unprivileged attachment broker.
-#if defined(OS_MACOSX)
- IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(
- MachBroker::GetInstance());
-#else
- IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
-#endif // defined(OS_MACOSX)
-#endif // USE_ATTACHMENT_BROKER
-
- scoped_refptr<base::SequencedTaskRunner> io_task_runner =
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
- shell::Connector* connector =
- BrowserContext::GetConnectorFor(browser_context_);
- // Some embedders may not initialize Mojo or the shell connector for a browser
- // context (e.g. Android WebView)... so just fall back to the per-process
- // connector.
- if (!connector) {
- // Additionally, some test code may not initialize the process-wide
- // ServiceManagerConnection prior to this point. This class of test code
- // doesn't care about render processes so we can initialize a dummy one.
- if (!ServiceManagerConnection::GetForProcess()) {
- shell::mojom::ServiceRequest request = mojo::GetProxy(&test_service_);
- ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
- std::move(request), io_task_runner));
- }
- connector = ServiceManagerConnection::GetForProcess()->GetConnector();
- }
- child_connection_.reset(new ChildConnection(
- kRendererServiceName,
- base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
- io_task_runner));
+ InitializeChannelProxy();
}
// static
@@ -787,8 +724,8 @@ void RenderProcessHostImpl::ShutDownInProcessRenderer() {
case 1: {
RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
AllHostsIterator().GetCurrentValue());
- FOR_EACH_OBSERVER(RenderProcessHostObserver, host->observers_,
- RenderProcessHostDestroyed(host));
+ for (auto& observer : host->observers_)
+ observer.RenderProcessHostDestroyed(host);
#ifndef NDEBUG
host->is_self_deleted_ = true;
#endif
@@ -824,13 +761,7 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
gpu_observer_registered_ = false;
}
-#if USE_ATTACHMENT_BROKER
- IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
- channel_.get());
-#endif
- // We may have some unsent messages at this point, but that's OK.
- channel_.reset();
- queued_messages_ = MessageQueue{};
+ is_dead_ = true;
UnregisterHost(GetID());
@@ -841,16 +772,14 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
}
}
-void RenderProcessHostImpl::EnableSendQueue() {
- is_initialized_ = false;
-}
-
bool RenderProcessHostImpl::Init() {
// calling Init() more than once does nothing, this makes it more convenient
// for the view host which may not be sure in some cases
- if (channel_)
+ if (HasConnection())
return true;
+ is_dead_ = false;
+
base::CommandLine::StringType renderer_prefix;
// A command prefix is something prepended to the command line of the spawned
// process.
@@ -872,32 +801,22 @@ bool RenderProcessHostImpl::Init() {
if (renderer_path.empty())
return false;
- channel_connected_ = false;
sent_render_process_ready_ = false;
- // Setup the IPC channel.
- channel_ = CreateChannelProxy();
+ // We may reach Init() during process death notification (e.g.
+ // RenderProcessExited on some observer). In this case the Channel may be
+ // null, so we re-initialize it here.
+ if (!channel_)
+ InitializeChannelProxy();
- // Note that Channel send is effectively paused and unpaused at various points
- // during startup, and existing code relies on a fragile relative message
- // ordering resulting from some early messages being queued until process
- // launch while others are sent immediately.
- //
- // We acquire a few associated interface proxies here -- before the channel is
- // paused -- to ensure that subsequent initialization messages on those
- // interfaces behave properly. Specifically, this avoids the risk of an
- // interface being requested while the Channel is paused, effectively
- // blocking the transmission of a subsequent message on the interface which
- // may be sent while the Channel is unpaused.
+ // Unpause the Channel briefly. This will be paused again below if we launch a
+ // real child process. Note that messages may be sent in the short window
+ // between now and then (e.g. in response to RenderProcessWillLaunch) and we
+ // depend on those messages being sent right away.
//
- // See OnProcessLaunched() for some additional details of this somewhat
- // surprising behavior.
- channel_->GetRemoteAssociatedInterface(&remote_route_provider_);
-
- std::unique_ptr<AssociatedInterfaceHolder<mojom::Renderer>> holder =
- base::MakeUnique<AssociatedInterfaceHolder<mojom::Renderer>>();
- channel_->GetRemoteAssociatedInterface(&holder->proxy());
- SetUserData(kRendererInterfaceKeyName, holder.release());
+ // |channel_| must always be non-null here: either it was initialized in
+ // the constructor, or in the most recent call to ProcessDied().
+ channel_->Unpause(false /* flush */);
// Call the embedder first so that their IPC filters have priority.
GetContentClient()->browser()->RenderProcessWillLaunch(this);
@@ -942,7 +861,6 @@ bool RenderProcessHostImpl::Init() {
// in-process plugins.
options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
#endif
-
// As for execution sequence, this callback should have no any dependency
// on starting in-process-render-thread.
// So put it here to trigger ChannelMojo initialization earlier to enable
@@ -953,6 +871,9 @@ bool RenderProcessHostImpl::Init() {
g_in_process_thread = in_process_renderer_->message_loop();
+ // Make sure any queued messages on the channel are flushed in the case
+ // where we aren't launching a child process.
+ channel_->Flush();
} else {
// Build command line for renderer. We call AppendRendererCommandLine()
// first so the process type argument will appear first.
@@ -965,61 +886,117 @@ bool RenderProcessHostImpl::Init() {
// As long as there's no renderer prefix, we can use the zygote process
// at this stage.
child_process_launcher_.reset(new ChildProcessLauncher(
- new RendererSandboxedProcessLauncherDelegate(channel_.get()), cmd_line,
- GetID(), this, child_token_,
- base::Bind(&RenderProcessHostImpl::OnMojoError, id_)));
+ new RendererSandboxedProcessLauncherDelegate(), cmd_line, GetID(), this,
+ child_token_, base::Bind(&RenderProcessHostImpl::OnMojoError, id_)));
channel_->Pause();
fast_shutdown_started_ = false;
}
- // Push any pending messages to the channel now. Note that if the child
- // process is still launching, the channel will be paused and outgoing
- // messages will be queued internally by the channel.
- while (!queued_messages_.empty()) {
- channel_->Send(queued_messages_.front().release());
- queued_messages_.pop();
- }
-
if (!gpu_observer_registered_) {
gpu_observer_registered_ = true;
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
}
- power_monitor_broadcaster_.Init();
-
is_initialized_ = true;
init_time_ = base::TimeTicks::Now();
return true;
}
-std::unique_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy() {
- scoped_refptr<base::SingleThreadTaskRunner> runner =
+void RenderProcessHostImpl::EnableSendQueue() {
+ if (!channel_)
+ InitializeChannelProxy();
+}
+
+void RenderProcessHostImpl::InitializeChannelProxy() {
+ // Generate a token used to identify the new child process.
+ child_token_ = mojo::edk::GenerateRandomToken();
+
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+
+ // Acquire a Connector which will route connections to a new instance of the
+ // renderer service.
+ service_manager::Connector* connector =
+ BrowserContext::GetConnectorFor(browser_context_);
+ if (!connector) {
+ // Note that some embedders (e.g. Android WebView) may not initialize a
+ // Connector per BrowserContext. In those cases we fall back to the
+ // browser-wide Connector.
+ if (!ServiceManagerConnection::GetForProcess()) {
+ // Additionally, some test code may not initialize the process-wide
+ // ServiceManagerConnection prior to this point. This class of test code
+ // doesn't care about render processes, so we can initialize a dummy
+ // connection.
+ service_manager::mojom::ServiceRequest request =
+ mojo::GetProxy(&test_service_);
+ ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
+ std::move(request), io_task_runner));
+ }
+ connector = ServiceManagerConnection::GetForProcess()->GetConnector();
+ }
+
+ // Establish a ServiceManager connection for the new render service instance.
+ child_connection_.reset(new ChildConnection(
+ mojom::kRendererServiceName,
+ base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
+ io_task_runner));
+
+ // Send an interface request to bootstrap the IPC::Channel. Note that this
+ // request will happily sit on the pipe until the process is launched and
+ // connected to the ServiceManager. We take the other end immediately and
+ // plug it into a new ChannelProxy.
IPC::mojom::ChannelBootstrapPtr bootstrap;
GetRemoteInterfaces()->GetInterface(&bootstrap);
std::unique_ptr<IPC::ChannelFactory> channel_factory =
IPC::ChannelMojo::CreateServerFactory(
- bootstrap.PassInterface().PassHandle(), runner);
+ bootstrap.PassInterface().PassHandle(), io_task_runner);
+
+ ResetChannelProxy();
- std::unique_ptr<IPC::ChannelProxy> channel;
// Do NOT expand ifdef or run time condition checks here! Synchronous
// IPCs from browser process are banned. It is only narrowly allowed
// for Android WebView to maintain backward compatibility.
// See crbug.com/526842 for details.
#if defined(OS_ANDROID)
- if (GetContentClient()->UsingSynchronousCompositing())
- channel = IPC::SyncChannel::Create(this, runner.get(), &never_signaled_);
+ if (GetContentClient()->UsingSynchronousCompositing()) {
+ channel_ = IPC::SyncChannel::Create(
+ this, io_task_runner.get(), &never_signaled_);
+ }
#endif // OS_ANDROID
- if (!channel)
- channel.reset(new IPC::ChannelProxy(this, runner.get()));
-#if USE_ATTACHMENT_BROKER
- IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
- channel.get(), runner);
-#endif
- channel->Init(std::move(channel_factory), true /* create_pipe_now */);
+ if (!channel_)
+ channel_.reset(new IPC::ChannelProxy(this, io_task_runner.get()));
+ channel_->Init(std::move(channel_factory), true /* create_pipe_now */);
+
+ // Note that Channel send is effectively paused and unpaused at various points
+ // during startup, and existing code relies on a fragile relative message
+ // ordering resulting from some early messages being queued until process
+ // launch while others are sent immediately. See https://goo.gl/REW75h for
+ // details.
+ //
+ // We acquire a few associated interface proxies here -- before the channel is
+ // paused -- to ensure that subsequent initialization messages on those
+ // interfaces behave properly. Specifically, this avoids the risk of an
+ // interface being requested while the Channel is paused, which could
+ // effectively and undesirably block the transmission of a subsequent message
+ // on that interface while the Channel is unpaused.
+ //
+ // See OnProcessLaunched() for some additional details of this somewhat
+ // surprising behavior.
+ channel_->GetRemoteAssociatedInterface(&remote_route_provider_);
+ channel_->GetRemoteAssociatedInterface(&renderer_interface_);
- return channel;
+ // We start the Channel in a paused state. It will be briefly unpaused again
+ // in Init() if applicable, before process launch is initiated.
+ channel_->Pause();
+}
+
+void RenderProcessHostImpl::ResetChannelProxy() {
+ if (!channel_)
+ return;
+
+ channel_.reset();
+ channel_connected_ = false;
}
void RenderProcessHostImpl::CreateMessageFilters() {
@@ -1073,7 +1050,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
storage_partition_impl_->GetAppCacheService(), blob_storage_context.get(),
storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetServiceWorkerContext(),
- storage_partition_impl_->GetHostZoomLevelContext(),
get_contexts_callback);
AddFilter(resource_message_filter_.get());
@@ -1096,7 +1072,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(audio_renderer_host_.get());
AddFilter(
new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
- AddFilter(new VideoCaptureHost(media_stream_manager));
AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(), GetID()));
AddFilter(new ClipboardMessageFilter(blob_storage_context));
@@ -1201,12 +1176,15 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), storage_partition_impl_->GetServiceWorkerContext()));
#if defined(OS_ANDROID)
AddFilter(new ScreenOrientationMessageFilterAndroid());
+ synchronous_compositor_filter_ =
+ new SynchronousCompositorBrowserFilter(GetID());
+ AddFilter(synchronous_compositor_filter_.get());
#endif
}
void RenderProcessHostImpl::RegisterMojoInterfaces() {
- std::unique_ptr<shell::InterfaceRegistry> registry(
- new shell::InterfaceRegistry);
+ auto registry = base::MakeUnique<service_manager::InterfaceRegistry>(
+ service_manager::mojom::kServiceManager_ConnectorSpec);
channel_->AddAssociatedInterface(
base::Bind(&RenderProcessHostImpl::OnRouteProviderRequest,
@@ -1226,6 +1204,13 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Unretained(permission_service_context_.get())));
// TODO(mcasas): finalize arguments.
AddUIThreadInterface(registry.get(), base::Bind(&ImageCaptureImpl::Create));
+
+ AddUIThreadInterface(
+ registry.get(),
+ base::Bind(&PaymentAppContext::CreateService,
+ base::Unretained(
+ storage_partition_impl_->GetPaymentAppContext())));
+
AddUIThreadInterface(
registry.get(),
base::Bind(&OffscreenCanvasCompositorFrameSinkProviderImpl::Create));
@@ -1266,22 +1251,40 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Unretained(
BrowserMainLoop::GetInstance()->time_zone_monitor())));
+ AddUIThreadInterface(
+ registry.get(),
+ base::Bind(&device::PowerMonitorMessageBroadcaster::Create));
+
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE);
registry->AddInterface(base::Bind(&MimeRegistryImpl::Create),
file_task_runner);
-#if defined(USE_MINIKIN_HYPHENATION)
+#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
registry->AddInterface(base::Bind(&hyphenation::HyphenationImpl::Create),
file_task_runner);
#endif
- // These callbacks will be run immediately on the IO thread.
+#if defined(OS_ANDROID)
+ // On Android the device sensors implementations need to run on the UI thread
+ // to communicate to Java.
+ AddUIThreadInterface(registry.get(), base::Bind(&DeviceLightHost::Create));
+ AddUIThreadInterface(registry.get(), base::Bind(&DeviceMotionHost::Create));
+ AddUIThreadInterface(registry.get(),
+ base::Bind(&DeviceOrientationHost::Create));
+ AddUIThreadInterface(registry.get(),
+ base::Bind(&DeviceOrientationAbsoluteHost::Create));
+#else
+ // On platforms other than Android the device sensors implementations run on
+ // the IO thread.
registry->AddInterface(base::Bind(&DeviceLightHost::Create));
registry->AddInterface(base::Bind(&DeviceMotionHost::Create));
registry->AddInterface(base::Bind(&DeviceOrientationHost::Create));
registry->AddInterface(base::Bind(&DeviceOrientationAbsoluteHost::Create));
+#endif // defined(OS_ANDROID)
+
registry->AddInterface(
- base::Bind(&URLLoaderFactoryImpl::Create, resource_message_filter_));
+ base::Bind(&VideoCaptureHost::Create,
+ BrowserMainLoop::GetInstance()->media_stream_manager()));
// This is to support usage of WebSockets in cases in which there is no
// associated RenderFrame (e.g., Shared Workers).
@@ -1339,7 +1342,8 @@ void RenderProcessHostImpl::ResumeDeferredNavigation(
widget_helper_->ResumeDeferredNavigation(request_id);
}
-shell::InterfaceProvider* RenderProcessHostImpl::GetRemoteInterfaces() {
+service_manager::InterfaceProvider*
+RenderProcessHostImpl::GetRemoteInterfaces() {
return child_connection_->GetRemoteInterfaces();
}
@@ -1411,26 +1415,16 @@ void RenderProcessHostImpl::PurgeAndSuspend() {
Send(new ChildProcessMsg_PurgeAndSuspend());
}
-mojom::RouteProvider* RenderProcessHostImpl::GetRemoteRouteProvider() {
- return remote_route_provider_.get();
+void RenderProcessHostImpl::Resume() {
+ Send(new ChildProcessMsg_Resume());
}
-// static
-mojom::Renderer* RenderProcessHostImpl::GetRendererInterface(
- RenderProcessHost* host) {
- AssociatedInterfaceHolder<mojom::Renderer>* holder =
- static_cast<AssociatedInterfaceHolder<mojom::Renderer>*>(
- host->GetUserData(kRendererInterfaceKeyName));
- if (!holder) {
- // In tests, MockRenderProcessHost will not have initialized this key on its
- // own. We do it with a dead-end endpoint so outgoing requests are silently
- // dropped.
- holder = new AssociatedInterfaceHolder<mojom::Renderer>;
- host->SetUserData(kRendererInterfaceKeyName, holder);
- mojo::GetDummyProxyForTesting(&holder->proxy());
- }
+mojom::Renderer* RenderProcessHostImpl::GetRendererInterface() {
+ return renderer_interface_.get();
+}
- return holder->proxy().get();
+mojom::RouteProvider* RenderProcessHostImpl::GetRemoteRouteProvider() {
+ return remote_route_provider_.get();
}
void RenderProcessHostImpl::AddRoute(int32_t routing_id,
@@ -1579,7 +1573,7 @@ static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
}
void RenderProcessHostImpl::AppendRendererCommandLine(
- base::CommandLine* command_line) const {
+ base::CommandLine* command_line) {
// Pass the process type first, so it shows first in process listings.
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kRendererProcess);
@@ -1614,11 +1608,13 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
command_line->AppendSwitchASCII(switches::kServiceRequestChannelToken,
child_connection_->service_token());
+ command_line->AppendSwitchASCII(switches::kRendererClientId,
+ std::to_string(GetID()));
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
const base::CommandLine& browser_cmd,
- base::CommandLine* renderer_cmd) const {
+ base::CommandLine* renderer_cmd) {
// Propagate the following switches to the renderer command line (along
// with any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
@@ -1653,6 +1649,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableLocalStorage,
switches::kDisableLogging,
switches::kDisableMediaSuspend,
+ switches::kDisableMojoServiceWorker,
switches::kDisableNotifications,
switches::kDisableOverlayScrollbar,
switches::kDisablePepper3DImageChromium,
@@ -1672,7 +1669,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableV8IdleTasks,
switches::kDisableWebGLImageChromium,
switches::kDomAutomationController,
- switches::kEnableAsmWasm,
switches::kEnableBlinkFeatures,
switches::kEnableBrowserSideNavigation,
switches::kEnableDisplayList2dCanvas,
@@ -1704,13 +1700,10 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableStatsTable,
switches::kEnableThreadedCompositing,
switches::kEnableTouchDragDrop,
- switches::kEnableUnsafeES3APIs,
switches::kEnableUseZoomForDSF,
switches::kEnableViewport,
switches::kEnableVp9InMp4,
switches::kEnableVtune,
- switches::kEnableWasm,
- switches::kEnableWebBluetooth,
switches::kEnableWebFontsInterventionTrigger,
switches::kEnableWebFontsInterventionV2,
switches::kEnableWebGLDraftExtensions,
@@ -1732,7 +1725,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kMaxUntiledLayerHeight,
switches::kMemoryMetrics,
switches::kMojoLocalStorage,
- switches::kMojoServiceWorker,
switches::kMSEAudioBufferSizeLimit,
switches::kMSEVideoBufferSizeLimit,
switches::kNoReferrers,
@@ -1755,7 +1747,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kTouchTextSelectionStrategy,
switches::kTraceConfigFile,
switches::kTraceToConsole,
- switches::kUseCrossProcessFramesForGuests,
switches::kUseFakeUIForMediaStream,
// This flag needs to be propagated to the renderer process for
// --in-process-webgl.
@@ -1784,8 +1775,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kShowScreenSpaceRects,
cc::switches::kShowSurfaceDamageRects,
cc::switches::kSlowDownRasterScaleFactor,
- cc::switches::kTopControlsHideThreshold,
- cc::switches::kTopControlsShowThreshold,
+ cc::switches::kBrowserControlsHideThreshold,
+ cc::switches::kBrowserControlsShowThreshold,
#if defined(ENABLE_PLUGINS)
switches::kEnablePepperTesting,
@@ -1793,7 +1784,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(ENABLE_WEBRTC)
switches::kDisableWebRtcHWDecoding,
switches::kDisableWebRtcHWEncoding,
- switches::kEnableWebRtcHWH264Encoding,
switches::kEnableWebRtcStunOrigin,
switches::kEnforceWebRtcIPPermissionCheck,
switches::kForceWebRtcIPHandlingPolicy,
@@ -1803,6 +1793,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableLowEndDeviceMode,
#if defined(OS_ANDROID)
switches::kDisableUnifiedMediaPipeline,
+ switches::kEnableContentIntentDetection,
switches::kRendererWaitForJavaDebugger,
#endif
#if defined(OS_MACOSX)
@@ -1810,7 +1801,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableSandboxLogging,
#endif
#if defined(OS_WIN)
- switches::kDisableWin32kRendererLockDown,
+ switches::kDisableWin32kLockDown,
switches::kEnableWin7WebRtcHWH264Decoding,
switches::kTrySupportedChannelLayouts,
switches::kTraceExportEventsToETW,
@@ -1951,26 +1942,24 @@ bool RenderProcessHostImpl::Send(IPC::Message* msg) {
std::unique_ptr<IPC::Message> message(msg);
+ // |channel_| is only null after Cleanup(), at which point we don't care about
+ // delivering any messages.
+ if (!channel_)
+ return false;
+
#if !defined(OS_ANDROID)
DCHECK(!message->is_sync());
-#endif
-
- if (!channel_) {
-#if defined(OS_ANDROID)
- if (message->is_sync())
+#else
+ if (message->is_sync()) {
+ // If Init() hasn't been called yet since construction or the last
+ // ProcessDied() we avoid blocking on sync IPC.
+ if (!HasConnection())
return false;
-#endif
- if (!is_initialized_) {
- queued_messages_.emplace(std::move(message));
- return true;
- }
- return false;
- }
-#if defined(OS_ANDROID)
- if (child_process_launcher_.get() && child_process_launcher_->IsStarting() &&
- message->is_sync()) {
- return false;
+ // Likewise if we've done Init(), but process launch has not yet completed,
+ // we avoid blocking on sync IPC.
+ if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
+ return false;
}
#endif
@@ -2030,9 +2019,8 @@ void RenderProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
DCHECK(!sent_render_process_ready_);
sent_render_process_ready_ = true;
// Send RenderProcessReady only if we already received the process handle.
- FOR_EACH_OBSERVER(RenderProcessHostObserver,
- observers_,
- RenderProcessReady(this));
+ for (auto& observer : observers_)
+ observer.RenderProcessReady(this);
}
#if defined(IPC_MESSAGE_LOG_ENABLED)
@@ -2084,7 +2072,7 @@ int RenderProcessHostImpl::GetID() const {
}
bool RenderProcessHostImpl::HasConnection() const {
- return channel_.get() != NULL;
+ return is_initialized_ && !is_dead_;
}
void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
@@ -2146,18 +2134,18 @@ void RenderProcessHostImpl::Cleanup() {
DCHECK_EQ(0, pending_views_);
- // If |channel_| is still valid, the process associated with this
- // RenderProcessHost is still alive. Notify all observers that the process
- // has exited cleanly, even though it will be destroyed a bit later.
- // Observers shouldn't rely on this process anymore.
- if (channel_.get()) {
- FOR_EACH_OBSERVER(
- RenderProcessHostObserver, observers_,
- RenderProcessExited(this, base::TERMINATION_STATUS_NORMAL_TERMINATION,
- 0));
- }
- FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_,
- RenderProcessHostDestroyed(this));
+ // If the process associated with this RenderProcessHost is still alive,
+ // notify all observers that the process has exited cleanly, even though it
+ // will be destroyed a bit later. Observers shouldn't rely on this process
+ // anymore.
+ if (HasConnection()) {
+ for (auto& observer : observers_) {
+ observer.RenderProcessExited(
+ this, base::TERMINATION_STATUS_NORMAL_TERMINATION, 0);
+ }
+ }
+ for (auto& observer : observers_)
+ observer.RenderProcessHostDestroyed(this);
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_TERMINATED,
Source<RenderProcessHost>(this), NotificationService::NoDetails());
@@ -2178,17 +2166,12 @@ void RenderProcessHostImpl::Cleanup() {
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
deleting_soon_ = true;
-#if USE_ATTACHMENT_BROKER
- IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
- channel_.get());
-#endif
-
// It's important not to wait for the DeleteTask to delete the channel
// proxy. Kill it off now. That way, in case the profile is going away, the
// rest of the objects attached to this RenderProcessHost start going
// away first, since deleting the channel proxy will post a
// OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
- channel_.reset();
+ ResetChannelProxy();
// The following members should be cleared in ProcessDied() as well!
message_port_message_filter_ = NULL;
@@ -2389,13 +2372,7 @@ void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph,
*url = GURL(url::kAboutBlankURL);
}
- // Do not allow browser plugin guests to navigate to non-web URLs, since they
- // cannot swap processes or grant bindings.
- bool non_web_url_in_guest =
- rph->IsForGuestsOnly() &&
- !(url->is_valid() && policy->IsWebSafeScheme(url->scheme()));
-
- if (non_web_url_in_guest || !policy->CanRequestURL(rph->GetID(), *url)) {
+ if (!policy->CanRequestURL(rph->GetID(), *url)) {
// If this renderer is not permitted to request this URL, we invalidate the
// URL. This prevents us from storing the blocked URL and becoming confused
// later.
@@ -2620,7 +2597,10 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
// method will get called a second time meaning that a metrics-allocator
// already exists. Don't recreate it.
if (!metrics_allocator_) {
- // TODO(bcwhite): Update this with the correct memory size.
+ // Create persistent/shared memory and allow histograms to be stored in
+ // it. Memory that is not actualy used won't be physically mapped by the
+ // system. RendererMetrics usage, as reported in UMA, peaked around 0.7MiB
+ // as of 2016-12-20.
std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory());
if (!shm->CreateAndMapAnonymous(2 << 20)) // 2 MiB
return;
@@ -2680,45 +2660,22 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
RendererClosedDetails details(status, exit_code);
child_process_launcher_.reset();
-#if USE_ATTACHMENT_BROKER
- IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
- channel_.get());
-#endif
- channel_.reset();
- queued_messages_ = MessageQueue{};
-
- // Clear all cached associated interface proxies as well, since these are
- // effectively bound to the lifetime of the Channel.
- remote_route_provider_.reset();
- RemoveUserData(kRendererInterfaceKeyName);
+ is_dead_ = true;
+ ResetChannelProxy();
UpdateProcessPriority();
DCHECK(!is_process_backgrounded_);
- // RenderProcessExited observers and RenderProcessGone handlers might
- // navigate or perform other actions that require a connection. Ensure that
- // there is one before calling them.
- child_token_ = mojo::edk::GenerateRandomToken();
- shell::Connector* connector =
- BrowserContext::GetConnectorFor(browser_context_);
- if (!connector)
- connector = ServiceManagerConnection::GetForProcess()->GetConnector();
- child_connection_.reset(new ChildConnection(
- kRendererServiceName,
- base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
-
within_process_died_observer_ = true;
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this),
Details<RendererClosedDetails>(&details));
- FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_,
- RenderProcessExited(this, status, exit_code));
+ for (auto& observer : observers_)
+ observer.RenderProcessExited(this, status, exit_code);
within_process_died_observer_ = false;
message_port_message_filter_ = NULL;
- DCHECK(!channel_);
RemoveUserData(kSessionStorageHolderKey);
IDMap<IPC::Listener>::iterator iter(&listeners_);
@@ -2728,6 +2685,13 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
iter.Advance();
}
+ // Initialize a new ChannelProxy in case this host is re-used for a new
+ // process. This ensures that new messages can be sent on the host ASAP (even
+ // before Init()) and they'll eventually reach the new process.
+ //
+ // Note that this may have already been called by one of the above observers
+ EnableSendQueue();
+
// It's possible that one of the calls out to the observers might have caused
// this object to be no longer needed.
if (delayed_cleanup_needed_)
@@ -2774,8 +2738,8 @@ void RenderProcessHostImpl::OnShutdownRequest() {
// Notify any contents that might have swapped out renderers from this
// process. They should not attempt to swap them back in.
- FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_,
- RenderProcessWillExit(this));
+ for (auto& observer : observers_)
+ observer.RenderProcessWillExit(this);
Send(new ChildProcessMsg_Shutdown());
}
@@ -2856,8 +2820,14 @@ void RenderProcessHostImpl::OnProcessLaunched() {
// Not all platforms launch processes in the same backgrounded state. Make
// sure |is_process_backgrounded_| reflects this platform's initial process
// state.
+#if defined(OS_MACOSX)
+ is_process_backgrounded_ =
+ child_process_launcher_->GetProcess().IsProcessBackgrounded(
+ MachBroker::GetInstance());
+#else
is_process_backgrounded_ =
child_process_launcher_->GetProcess().IsProcessBackgrounded();
+#endif // defined(OS_MACOSX)
// Disable updating process priority on startup for now as it incorrectly
// results in backgrounding foreground navigations until their first commit
@@ -2890,9 +2860,8 @@ void RenderProcessHostImpl::OnProcessLaunched() {
DCHECK(!sent_render_process_ready_);
sent_render_process_ready_ = true;
// Send RenderProcessReady only if the channel is already connected.
- FOR_EACH_OBSERVER(RenderProcessHostObserver,
- observers_,
- RenderProcessReady(this));
+ for (auto& observer : observers_)
+ observer.RenderProcessReady(this);
}
#if defined(ENABLE_WEBRTC)
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 f07c487e4e5..93c9fd00a34 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -22,7 +22,6 @@
#include "build/build_config.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
-#include "content/browser/power_monitor_message_broadcaster.h"
#include "content/browser/webrtc/webrtc_eventlog_host.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_export.h"
@@ -34,25 +33,21 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "services/shell/public/cpp/interface_registry.h"
-#include "services/shell/public/interfaces/service.mojom.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
+#include "services/service_manager/public/interfaces/service.mojom.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h"
+#if defined(OS_ANDROID)
+#include "content/browser/android/synchronous_compositor_browser_filter.h"
+#endif
+
namespace base {
class CommandLine;
class MessageLoop;
class SharedPersistentMemoryAllocator;
}
-namespace gfx {
-class Size;
-}
-
-namespace IPC {
-class ChannelMojoHost;
-}
-
namespace content {
class AudioInputRendererHost;
class AudioRendererHost;
@@ -69,15 +64,13 @@ class RendererMainThread;
class RenderFrameMessageFilter;
class RenderWidgetHelper;
class RenderWidgetHost;
-class RenderWidgetHostImpl;
-class RenderWidgetHostViewFrameSubscriber;
class ResourceMessageFilter;
class StoragePartition;
class StoragePartitionImpl;
namespace mojom {
class StoragePartitionService;
-}
+} // namespace mojom
typedef base::Thread* (*RendererMainThreadFactoryFunction)(
const InProcessChildThreadParams& params);
@@ -114,8 +107,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
~RenderProcessHostImpl() override;
// RenderProcessHost implementation (public portion).
- void EnableSendQueue() override;
bool Init() override;
+ void EnableSendQueue() override;
int GetNextRoutingID() override;
void AddRoute(int32_t routing_id, IPC::Listener* listener) override;
void RemoveRoute(int32_t routing_id) override;
@@ -163,7 +156,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
const WebRtcRtpPacketCallback& packet_callback) override;
#endif
void ResumeDeferredNavigation(const GlobalRequestID& request_id) override;
- shell::InterfaceProvider* GetRemoteInterfaces() override;
+ service_manager::InterfaceProvider* GetRemoteInterfaces() override;
std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
@@ -175,11 +168,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
void ForceReleaseWorkerRefCounts() override;
bool IsWorkerRefCountDisabled() override;
void PurgeAndSuspend() override;
+ void Resume() override;
+ mojom::Renderer* GetRendererInterface() override;
mojom::RouteProvider* GetRemoteRouteProvider();
- static mojom::Renderer* GetRendererInterface(RenderProcessHost* host);
-
// IPC::Sender via RenderProcessHost.
bool Send(IPC::Message* msg) override;
@@ -263,6 +256,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
return notification_message_filter_.get();
}
+#if defined(OS_ANDROID)
+ SynchronousCompositorBrowserFilter* synchronous_compositor_filter() const {
+ return synchronous_compositor_filter_.get();
+ }
+#endif
+
void set_is_for_guests_only_for_testing(bool is_for_guests_only) {
is_for_guests_only_ = is_for_guests_only;
}
@@ -307,7 +306,13 @@ class CONTENT_EXPORT RenderProcessHostImpl
return service_worker_ref_count_ + shared_worker_ref_count_;
}
- std::unique_ptr<IPC::ChannelProxy> CreateChannelProxy();
+ // Initializes a new IPC::ChannelProxy in |channel_|, which will be connected
+ // to the next child process launched for this host, if any.
+ void InitializeChannelProxy();
+
+ // Resets |channel_|, removing it from the attachment broker if necessary.
+ // Always call this in lieu of directly resetting |channel_|.
+ void ResetChannelProxy();
// Creates and adds the IO thread message filters.
void CreateMessageFilters();
@@ -336,14 +341,14 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Generates a command line to be used to spawn a renderer and appends the
// results to |*command_line|.
- void AppendRendererCommandLine(base::CommandLine* command_line) const;
+ void AppendRendererCommandLine(base::CommandLine* command_line);
// Copies applicable command line switches from the given |browser_cmd| line
// flags to the output |renderer_cmd| line flags. Not all switches will be
// copied over.
void PropagateBrowserCommandLineToRenderer(
const base::CommandLine& browser_cmd,
- base::CommandLine* renderer_cmd) const;
+ base::CommandLine* renderer_cmd);
// Inspects the current object state and sets/removes background priority if
// appropriate. Should be called after any of the involved data members
@@ -402,7 +407,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// the render process currently hosted by the RPHI. Callbacks added by this
// method will never run beyond the next invocation of Cleanup().
template <typename CallbackType>
- void AddUIThreadInterface(shell::InterfaceRegistry* registry,
+ void AddUIThreadInterface(service_manager::InterfaceRegistry* registry,
const CallbackType& callback) {
registry->AddInterface(
base::Bind(&InterfaceGetter<CallbackType>::GetInterfaceOnUIThread,
@@ -416,7 +421,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
int connection_filter_id_ =
ServiceManagerConnection::kInvalidConnectionFilterId;
scoped_refptr<ConnectionFilterController> connection_filter_controller_;
- shell::mojom::ServicePtr test_service_;
+ service_manager::mojom::ServicePtr test_service_;
size_t service_worker_ref_count_;
size_t shared_worker_ref_count_;
@@ -455,12 +460,19 @@ class CONTENT_EXPORT RenderProcessHostImpl
// closure per notification that must be freed when the notification closes.
scoped_refptr<NotificationMessageFilter> notification_message_filter_;
+#if defined(OS_ANDROID)
+ scoped_refptr<SynchronousCompositorBrowserFilter>
+ synchronous_compositor_filter_;
+#endif
+
// Used in single-process mode.
std::unique_ptr<base::Thread> in_process_renderer_;
- // True after Init() has been called. We can't just check channel_ because we
- // also reset that in the case of process termination.
- bool is_initialized_;
+ // True after Init() has been called.
+ bool is_initialized_ = false;
+
+ // True after ProcessDied(), until the next call to Init().
+ bool is_dead_ = false;
// PlzNavigate
// Stores the time at which the first call to Init happened.
@@ -469,16 +481,13 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Used to launch and terminate the process without blocking the UI thread.
std::unique_ptr<ChildProcessLauncher> child_process_launcher_;
- // Messages we queue before the ChannelProxy is created.
- using MessageQueue = std::queue<std::unique_ptr<IPC::Message>>;
- MessageQueue queued_messages_;
-
// The globally-unique identifier for this RPH.
const int id_;
- // A secondary ID used by the Mojo shell to distinguish different incarnations
- // of the same RPH from each other. Unlike |id_| this is not globally unique,
- // but it is guaranteed to change every time Init() is called.
+ // A secondary ID used by the Service Manager to distinguish different
+ // incarnations of the same RPH from each other. Unlike |id_| this is not
+ // globally unique, but it is guaranteed to change every time ProcessDied() is
+ // called.
int instance_id_ = 1;
BrowserContext* browser_context_;
@@ -520,9 +529,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
// through RenderProcessHostObserver::RenderProcessExited.
bool within_process_died_observer_;
- // Forwards power state messages to the renderer process.
- PowerMonitorMessageBroadcaster power_monitor_broadcaster_;
-
scoped_refptr<AudioRendererHost> audio_renderer_host_;
scoped_refptr<AudioInputRendererHost> audio_input_renderer_host_;
@@ -573,6 +579,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<ResourceMessageFilter> resource_message_filter_;
mojom::RouteProviderAssociatedPtr remote_route_provider_;
+ mojom::RendererAssociatedPtr renderer_interface_;
// A WeakPtrFactory which is reset every time Cleanup() runs. Used to vend
// WeakPtrs which are invalidated any time the RPHI is recycled.
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.cc b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
index 2ce7f964a12..d9d33b282bd 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
@@ -52,4 +52,16 @@ bool RenderViewHostDelegate::IsOverridingUserAgent() {
return false;
}
+bool RenderViewHostDelegate::IsJavaScriptDialogShowing() const {
+ return false;
+}
+
+bool RenderViewHostDelegate::HideDownloadUI() const {
+ return false;
+}
+
+bool RenderViewHostDelegate::IsFocusedElementEditable() {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index ef18d5d2fb8..0f7fd3feed7 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -19,13 +19,6 @@
#include "ui/base/window_open_disposition.h"
class GURL;
-class SkBitmap;
-struct FrameHostMsg_DidCommitProvisionalLoad_Params;
-
-namespace base {
-class ListValue;
-class TimeTicks;
-}
namespace IPC {
class Message;
@@ -39,7 +32,6 @@ class Size;
namespace content {
class BrowserContext;
-class CrossSiteTransferringRequest;
class FrameTree;
class PageState;
class RenderViewHost;
@@ -47,13 +39,7 @@ class RenderViewHostDelegateView;
class SessionStorageNamespace;
class SiteInstance;
class WebContents;
-class WebContentsImpl;
-struct FileChooserParams;
-struct GlobalRequestID;
-struct NativeWebKeyboardEvent;
-struct Referrer;
struct RendererPreferences;
-struct WebPreferences;
namespace mojom {
class CreateNewWindowParams;
@@ -105,7 +91,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// The state for the page changed and should be updated.
virtual void UpdateState(RenderViewHost* render_view_host,
- int32_t page_id,
const PageState& state) {}
// The destination URL has changed should be updated.
@@ -240,6 +225,19 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// Desktop Site" feature.
virtual bool IsOverridingUserAgent();
+ virtual bool IsJavaScriptDialogShowing() const;
+
+ // Whether download UI should be hidden.
+ virtual bool HideDownloadUI() const;
+
+ // Whether the focused element on the page is editable. This returns true iff
+ // the focused frame has a focused editable element.
+ virtual bool IsFocusedElementEditable();
+
+ // Asks the delegate to clear the focused element. This will lead to an IPC to
+ // the focused RenderWidget.
+ virtual void ClearFocusedElement() {}
+
protected:
virtual ~RenderViewHostDelegate() {}
};
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
index 3fdd338b3ea..c3633435e27 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
@@ -13,28 +13,21 @@
#include "content/common/drag_event_source_info.h"
#include "third_party/WebKit/public/platform/WebDragOperation.h"
-class SkBitmap;
-
namespace gfx {
class ImageSkia;
class Rect;
class Vector2d;
}
-namespace ui {
-class GestureEvent;
-class MouseEvent;
-}
-
namespace content {
class RenderFrameHost;
+class RenderWidgetHostImpl;
struct ContextMenuParams;
struct DropData;
struct MenuItem;
// This class provides a way for the RenderViewHost to reach out to its
-// delegate's view. It only needs to be implemented by embedders if they don't
-// use the default WebContentsView implementations.
+// delegate's view.
class CONTENT_EXPORT RenderViewHostDelegateView {
public:
// A context menu should be shown, to be built using the context information
@@ -51,7 +44,8 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {}
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {}
// The page wants to update the mouse cursor during a drag & drop operation.
// |operation| describes the current operation (none, move, copy, link.)
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.h b/chromium/content/browser/renderer_host/render_view_host_factory.h
index a6f7dd5e6ce..51babd49079 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -11,11 +11,9 @@
#include "content/common/content_export.h"
namespace content {
-class RenderFrameHostDelegate;
class RenderViewHost;
class RenderViewHostDelegate;
class RenderWidgetHostDelegate;
-class SessionStorageNamespace;
class SiteInstance;
// A factory for creating RenderViewHosts. There is a global factory function
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 050a8554ea7..84dcbd4be1d 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -19,6 +19,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
@@ -27,6 +28,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
+#include "components/variations/variations_associated_data.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
@@ -36,7 +38,6 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
@@ -44,7 +45,6 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/drag_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
@@ -59,7 +59,6 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
@@ -73,16 +72,13 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
-#include "content/public/common/drop_data.h"
#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
-#include "net/base/filename_util.h"
#include "net/base/url_util.h"
#include "net/url_request/url_request_context_getter.h"
-#include "storage/browser/fileapi/isolated_context.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/touch/touch_device.h"
@@ -103,9 +99,6 @@
using base::TimeDelta;
using blink::WebConsoleMessage;
-using blink::WebDragOperation;
-using blink::WebDragOperationNone;
-using blink::WebDragOperationsMask;
using blink::WebInputEvent;
using blink::WebMediaPlayerAction;
using blink::WebPluginAction;
@@ -113,8 +106,8 @@ using blink::WebPluginAction;
namespace content {
namespace {
+void GetPlatformSpecificPrefs(RendererPreferences* prefs) {
#if defined(OS_WIN)
-void GetWindowsSpecificPrefs(RendererPreferences* prefs) {
NONCLIENTMETRICS_XP metrics = {0};
base::win::GetNonClientMetrics(&metrics);
@@ -146,57 +139,9 @@ void GetWindowsSpecificPrefs(RendererPreferences* prefs) {
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYVSCROLL);
prefs->arrow_bitmap_width_horizontal_scroll_bar_in_dips =
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXHSCROLL);
-}
+#elif defined(OS_LINUX)
+ prefs->system_font_family_name = gfx::Font().GetFontName();
#endif
-
-std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
- std::vector<DropData::Metadata> metadata;
- if (!drop_data.text.is_null()) {
- metadata.push_back(DropData::Metadata::CreateForMimeType(
- DropData::Kind::STRING,
- base::ASCIIToUTF16(ui::Clipboard::kMimeTypeText)));
- }
-
- if (drop_data.url.is_valid()) {
- metadata.push_back(DropData::Metadata::CreateForMimeType(
- DropData::Kind::STRING,
- base::ASCIIToUTF16(ui::Clipboard::kMimeTypeURIList)));
- }
-
- if (!drop_data.html.is_null()) {
- metadata.push_back(DropData::Metadata::CreateForMimeType(
- DropData::Kind::STRING,
- base::ASCIIToUTF16(ui::Clipboard::kMimeTypeHTML)));
- }
-
- // On Aura, filenames are available before drop.
- for (const auto& file_info : drop_data.filenames) {
- if (!file_info.path.empty()) {
- metadata.push_back(DropData::Metadata::CreateForFilePath(file_info.path));
- }
- }
-
- // On Android, only files' mime types are available before drop.
- for (const auto& mime_type : drop_data.file_mime_types) {
- if (!mime_type.empty()) {
- metadata.push_back(DropData::Metadata::CreateForMimeType(
- DropData::Kind::FILENAME, mime_type));
- }
- }
-
- for (const auto& file_system_file : drop_data.file_system_files) {
- if (!file_system_file.url.is_empty()) {
- metadata.push_back(
- DropData::Metadata::CreateForFileSystemUrl(file_system_file.url));
- }
- }
-
- for (const auto& custom_data_item : drop_data.custom_data) {
- metadata.push_back(DropData::Metadata::CreateForMimeType(
- DropData::Kind::STRING, custom_data_item.first));
- }
-
- return metadata;
}
} // namespace
@@ -255,14 +200,12 @@ RenderViewHostImpl::RenderViewHostImpl(
delegate_(delegate),
instance_(static_cast<SiteInstanceImpl*>(instance)),
enabled_bindings_(0),
- page_id_(-1),
is_active_(!swapped_out),
is_swapped_out_(swapped_out),
main_frame_routing_id_(main_frame_routing_id),
is_waiting_for_close_ack_(false),
sudden_termination_allowed_(false),
render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
- is_focused_element_editable_(false),
updating_web_preferences_(false),
render_view_ready_on_process_launch_(false),
weak_factory_(this) {
@@ -272,6 +215,11 @@ RenderViewHostImpl::RenderViewHostImpl(
GetWidget()->set_owner_delegate(this);
GetProcess()->AddObserver(this);
+
+ // New views may be created during RenderProcessHost::ProcessDied(), within a
+ // brief window where the internal ChannelProxy is null. This ensures that the
+ // ChannelProxy is re-initialized in such cases so that subsequent messages
+ // make their way to the new renderer once its restarted.
GetProcess()->EnableSendQueue();
if (ResourceDispatcherHostImpl::Get()) {
@@ -307,7 +255,6 @@ SiteInstanceImpl* RenderViewHostImpl::GetSiteInstance() const {
bool RenderViewHostImpl::CreateRenderView(
int opener_frame_route_id,
int proxy_route_id,
- int32_t max_page_id,
const FrameReplicationState& replicated_frame_state,
bool window_was_created_with_opener) {
TRACE_EVENT0("renderer_host,navigation",
@@ -335,18 +282,10 @@ bool RenderViewHostImpl::CreateRenderView(
GetWidget()->set_renderer_initialized(true);
- // Ensure the RenderView starts with a next_page_id larger than any existing
- // page ID it might be asked to render.
- int32_t next_page_id = 1;
- if (max_page_id > -1)
- next_page_id = max_page_id + 1;
-
mojom::CreateViewParamsPtr params = mojom::CreateViewParams::New();
params->renderer_preferences =
delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
-#if defined(OS_WIN)
- GetWindowsSpecificPrefs(&params->renderer_preferences);
-#endif
+ GetPlatformSpecificPrefs(&params->renderer_preferences);
params->web_preferences = GetWebkitPreferences();
params->view_id = GetRoutingID();
params->main_frame_routing_id = main_frame_routing_id_;
@@ -367,7 +306,6 @@ bool RenderViewHostImpl::CreateRenderView(
params->hidden = GetWidget()->is_hidden();
params->never_visible = delegate_->IsNeverVisible();
params->window_was_created_with_opener = window_was_created_with_opener;
- params->next_page_id = next_page_id;
params->enable_auto_resize = GetWidget()->auto_resize_enabled();
params->min_size = GetWidget()->min_size_for_auto_resize();
params->max_size = GetWidget()->max_size_for_auto_resize();
@@ -377,15 +315,7 @@ bool RenderViewHostImpl::CreateRenderView(
GetWidget()->GetResizeParams(&params->initial_size);
GetWidget()->SetInitialRenderSizeParams(params->initial_size);
- RenderProcessHostImpl::GetRendererInterface(GetProcess())->CreateView(
- std::move(params));
-
- // If the RWHV has not yet been set, the surface ID namespace will get
- // passed down by the call to SetView().
- if (GetWidget()->GetView()) {
- Send(new ViewMsg_SetFrameSinkId(GetRoutingID(),
- GetWidget()->GetView()->GetFrameSinkId()));
- }
+ GetProcess()->GetRendererInterface()->CreateView(std::move(params));
// If it's enabled, tell the renderer to set up the Javascript bindings for
// sending messages back to the browser.
@@ -414,12 +344,27 @@ bool RenderViewHostImpl::IsRenderViewLive() const {
void RenderViewHostImpl::SyncRendererPrefs() {
RendererPreferences renderer_preferences =
delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
-#if defined(OS_WIN)
- GetWindowsSpecificPrefs(&renderer_preferences);
-#endif
+ GetPlatformSpecificPrefs(&renderer_preferences);
Send(new ViewMsg_SetRendererPrefs(GetRoutingID(), renderer_preferences));
}
+namespace {
+
+void SetFloatParameterFromMap(
+ const std::map<std::string, std::string>& settings,
+ const std::string& setting_name,
+ float* value) {
+ const auto& find_it = settings.find(setting_name);
+ if (find_it == settings.end())
+ return;
+ double parsed_value;
+ if (!base::StringToDouble(find_it->second, &parsed_value))
+ return;
+ *value = parsed_value;
+}
+
+} // namespace
+
WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
TRACE_EVENT0("browser", "RenderViewHostImpl::GetWebkitPrefs");
WebPreferences prefs;
@@ -475,8 +420,7 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.inert_visual_viewport =
command_line.HasSwitch(switches::kInertVisualViewport);
- prefs.pinch_overlay_scrollbar_thickness = 10;
- prefs.use_solid_color_scrollbars = ui::IsOverlayScrollbarEnabled();
+ prefs.use_solid_color_scrollbars = false;
prefs.history_entry_requires_user_gesture =
command_line.HasSwitch(switches::kHistoryEntryRequiresUserGesture);
@@ -490,10 +434,10 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
switches::kDisableGestureRequirementForMediaPlayback) &&
(autoplay_group_name.empty() || autoplay_group_name != "Enabled");
- prefs.autoplay_muted_videos_enabled =
- base::FeatureList::IsEnabled(features::kAutoplayMutedVideos);
prefs.progress_bar_completion = GetProgressBarCompletionPolicy();
+
+ prefs.use_solid_color_scrollbars = true;
#endif
// Handle autoplay gesture override experiment.
@@ -575,6 +519,23 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.user_gesture_required_for_presentation = !command_line.HasSwitch(
switches::kDisableGestureRequirementForPresentation);
+ if (delegate_ && delegate_->HideDownloadUI())
+ prefs.hide_download_ui = true;
+
+ std::map<std::string, std::string> expensive_background_throttling_prefs;
+ variations::GetVariationParamsByFeature(
+ features::kExpensiveBackgroundTimerThrottling,
+ &expensive_background_throttling_prefs);
+ SetFloatParameterFromMap(expensive_background_throttling_prefs, "cpu_budget",
+ &prefs.expensive_background_throttling_cpu_budget);
+ SetFloatParameterFromMap(
+ expensive_background_throttling_prefs, "initial_budget",
+ &prefs.expensive_background_throttling_initial_budget);
+ SetFloatParameterFromMap(expensive_background_throttling_prefs, "max_budget",
+ &prefs.expensive_background_throttling_max_budget);
+ SetFloatParameterFromMap(expensive_background_throttling_prefs, "max_delay",
+ &prefs.expensive_background_throttling_max_delay);
+
GetContentClient()->browser()->OverrideWebkitPrefs(this, &prefs);
return prefs;
}
@@ -583,12 +544,18 @@ void RenderViewHostImpl::ClosePage() {
is_waiting_for_close_ack_ = true;
GetWidget()->StartHangMonitorTimeout(
TimeDelta::FromMilliseconds(kUnloadTimeoutMS),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
+ blink::WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
- if (IsRenderViewLive()) {
+ bool is_javascript_dialog_showing = delegate_->IsJavaScriptDialogShowing();
+
+ // If there is a JavaScript dialog up, don't bother sending the renderer the
+ // close event because it is known unresponsive, waiting for the reply from
+ // the dialog.
+ if (IsRenderViewLive() && !is_javascript_dialog_showing) {
// Since we are sending an IPC message to the renderer, increase the event
// count to prevent the hang monitor timeout from being stopped by input
- // event acknowledgements.
+ // event acknowledgments.
GetWidget()->increment_in_flight_event_count();
// TODO(creis): Should this be moved to Shutdown? It may not be called for
@@ -600,7 +567,7 @@ void RenderViewHostImpl::ClosePage() {
Send(new ViewMsg_ClosePage(GetRoutingID()));
} else {
- // This RenderViewHost doesn't have a live renderer, so just skip the unload
+ // This RenderViewHost doesn't have a live renderer, so just skip the close
// event and close the page.
ClosePageIgnoringUnloadEvents();
}
@@ -631,74 +598,6 @@ void RenderViewHostImpl::RenderProcessExited(RenderProcessHost* host,
delegate_->RenderViewTerminated(this, status, exit_code);
}
-void RenderViewHostImpl::DragTargetDragEnter(
- const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- WebDragOperationsMask operations_allowed,
- int key_modifiers) {
- DragTargetDragEnterWithMetaData(DropDataToMetaData(drop_data), client_pt,
- screen_pt, operations_allowed, key_modifiers);
-}
-
-void RenderViewHostImpl::DragTargetDragEnterWithMetaData(
- const std::vector<DropData::Metadata>& metadata,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- WebDragOperationsMask operations_allowed,
- int key_modifiers) {
- Send(new DragMsg_TargetDragEnter(GetRoutingID(), metadata, client_pt,
- screen_pt, operations_allowed,
- key_modifiers));
-}
-
-void RenderViewHostImpl::DragTargetDragOver(
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- WebDragOperationsMask operations_allowed,
- int key_modifiers) {
- Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt, screen_pt,
- operations_allowed, key_modifiers));
-}
-
-void RenderViewHostImpl::DragTargetDragLeave() {
- Send(new DragMsg_TargetDragLeave(GetRoutingID()));
-}
-
-void RenderViewHostImpl::DragTargetDrop(const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- int key_modifiers) {
- DropData drop_data_with_permissions(drop_data);
- GrantFileAccessFromDropData(&drop_data_with_permissions);
- Send(new DragMsg_TargetDrop(GetRoutingID(), drop_data_with_permissions,
- client_pt, screen_pt, key_modifiers));
-}
-
-void RenderViewHostImpl::FilterDropData(DropData* drop_data) {
-#if DCHECK_IS_ON()
- drop_data->view_id = GetRoutingID();
-#endif // DCHECK_IS_ON()
-
- GetProcess()->FilterURL(true, &drop_data->url);
- if (drop_data->did_originate_from_renderer) {
- drop_data->filenames.clear();
- }
-}
-
-void RenderViewHostImpl::DragSourceEndedAt(
- int client_x, int client_y, int screen_x, int screen_y,
- WebDragOperation operation) {
- Send(new DragMsg_SourceEnded(GetRoutingID(),
- gfx::Point(client_x, client_y),
- gfx::Point(screen_x, screen_y),
- operation));
-}
-
-void RenderViewHostImpl::DragSourceSystemDragEnded() {
- Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
-}
-
bool RenderViewHostImpl::Send(IPC::Message* msg) {
return GetWidget()->Send(msg);
}
@@ -853,14 +752,10 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnDidContentsPreferredSizeChange)
IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
OnRouteCloseEvent)
- IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
- IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -937,14 +832,7 @@ void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
// decoupled.
}
-void RenderViewHostImpl::OnUpdateState(int32_t page_id,
- const PageState& state) {
- // If the following DCHECK fails, you have encountered a tricky edge-case that
- // has evaded reproduction for a very long time. Please report what you were
- // doing on http://crbug.com/407376, whether or not you can reproduce the
- // failure.
- DCHECK_EQ(page_id, page_id_);
-
+void RenderViewHostImpl::OnUpdateState(const PageState& state) {
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
@@ -955,7 +843,7 @@ void RenderViewHostImpl::OnUpdateState(int32_t page_id,
return;
}
- delegate_->UpdateState(this, page_id, state);
+ delegate_->UpdateState(this, state);
}
void RenderViewHostImpl::OnUpdateTargetURL(const GURL& url) {
@@ -1003,101 +891,12 @@ void RenderViewHostImpl::OnRouteCloseEvent() {
delegate_->RouteCloseEvent(this);
}
-void RenderViewHostImpl::OnStartDragging(
- const DropData& drop_data,
- WebDragOperationsMask drag_operations_mask,
- const SkBitmap& bitmap,
- const gfx::Vector2d& bitmap_offset_in_dip,
- const DragEventSourceInfo& event_info) {
- RenderViewHostDelegateView* view = delegate_->GetDelegateView();
- if (!view) {
- // Need to clear drag and drop state in blink.
- DragSourceSystemDragEnded();
- return;
- }
-
- DropData filtered_data(drop_data);
- RenderProcessHost* process = GetProcess();
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
- if (!filtered_data.url.SchemeIs(url::kJavaScriptScheme))
- process->FilterURL(true, &filtered_data.url);
- process->FilterURL(false, &filtered_data.html_base_url);
- // Filter out any paths that the renderer didn't have access to. This prevents
- // the following attack on a malicious renderer:
- // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
- // doesn't have read permissions for.
- // 2. We initiate a native DnD operation.
- // 3. DnD operation immediately ends since mouse is not held down. DnD events
- // still fire though, which causes read permissions to be granted to the
- // renderer for any file paths in the drop.
- filtered_data.filenames.clear();
- for (std::vector<ui::FileInfo>::const_iterator it =
- drop_data.filenames.begin();
- it != drop_data.filenames.end();
- ++it) {
- if (policy->CanReadFile(GetProcess()->GetID(), it->path))
- filtered_data.filenames.push_back(*it);
- }
-
- storage::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
- GetSiteInstance())
- ->GetFileSystemContext();
- filtered_data.file_system_files.clear();
- for (size_t i = 0; i < drop_data.file_system_files.size(); ++i) {
- storage::FileSystemURL file_system_url =
- file_system_context->CrackURL(drop_data.file_system_files[i].url);
- if (policy->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url))
- filtered_data.file_system_files.push_back(drop_data.file_system_files[i]);
- }
-
- float scale = GetScaleFactorForView(GetWidget()->GetView());
- gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale));
- view->StartDragging(filtered_data, drag_operations_mask, image,
- bitmap_offset_in_dip, event_info);
-}
-
-void RenderViewHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
- RenderViewHostDelegateView* view = delegate_->GetDelegateView();
- if (view)
- view->UpdateDragCursor(current_op);
-}
-
void RenderViewHostImpl::OnTakeFocus(bool reverse) {
RenderViewHostDelegateView* view = delegate_->GetDelegateView();
if (view)
view->TakeFocus(reverse);
}
-void RenderViewHostImpl::OnFocusedNodeChanged(
- bool is_editable_node,
- const gfx::Rect& node_bounds_in_viewport) {
- is_focused_element_editable_ = is_editable_node;
-
- // None of the rest makes sense without a view.
- if (!GetWidget()->GetView())
- return;
-
- // Convert node_bounds to screen coordinates.
- gfx::Rect view_bounds_in_screen = GetWidget()->GetView()->GetViewBounds();
- gfx::Point origin = node_bounds_in_viewport.origin();
- origin.Offset(view_bounds_in_screen.x(), view_bounds_in_screen.y());
- gfx::Rect node_bounds_in_screen(origin.x(), origin.y(),
- node_bounds_in_viewport.width(),
- node_bounds_in_viewport.height());
-
- GetWidget()->GetView()->FocusedNodeChanged(
- is_editable_node, node_bounds_in_screen);
-
- FocusedNodeDetails details = {is_editable_node, node_bounds_in_screen};
- NotificationService::current()->Notify(NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
- Source<RenderViewHost>(this),
- Details<FocusedNodeDetails>(&details));
-}
-
void RenderViewHostImpl::OnClosePageACK() {
GetWidget()->decrement_in_flight_event_count();
ClosePageIgnoringUnloadEvents();
@@ -1151,12 +950,16 @@ void RenderViewHostImpl::OnWebkitPreferencesChanged() {
}
void RenderViewHostImpl::ClearFocusedElement() {
- is_focused_element_editable_ = false;
- Send(new ViewMsg_ClearFocusedElement(GetRoutingID()));
+ // TODO(ekaramad): We should move this to WebContents instead
+ // (https://crbug.com/675975).
+ if (delegate_)
+ delegate_->ClearFocusedElement();
}
bool RenderViewHostImpl::IsFocusedElementEditable() {
- return is_focused_element_editable_;
+ // TODO(ekaramad): We should move this to WebContents instead
+ // (https://crbug.com/675975).
+ return delegate_ && delegate_->IsFocusedElementEditable();
}
void RenderViewHostImpl::Zoom(PageZoom zoom) {
@@ -1209,25 +1012,6 @@ void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
net::GetHostOrSpecFromURL(url));
}
-void RenderViewHostImpl::OnFocusedNodeTouched(bool editable) {
-#if defined(OS_WIN)
- // We use the cursor position to determine where the touch occurred.
- // TODO(ananta)
- // Pass this information from blink.
- // In site isolation mode, we may not have a RenderViewHostImpl instance
- // which means that displaying the OSK is not going to work. We should
- // probably move this to RenderWidgetHostImpl and call the view from there.
- // https://bugs.chromium.org/p/chromium/issues/detail?id=613326
- POINT cursor_pos = {};
- ::GetCursorPos(&cursor_pos);
- float scale = GetScaleFactorForView(GetWidget()->GetView());
- gfx::Point location_dips_screen =
- gfx::ConvertPointToDIP(scale, gfx::Point(cursor_pos));
- if (GetWidget()->GetView())
- GetWidget()->GetView()->FocusedNodeTouched(location_dips_screen, editable);
-#endif
-}
-
void RenderViewHostImpl::SelectWordAroundCaret() {
Send(new ViewMsg_SelectWordAroundCaret(GetRoutingID()));
}
@@ -1248,88 +1032,4 @@ void RenderViewHostImpl::RenderViewReady() {
delegate_->RenderViewReady(this);
}
-void RenderViewHostImpl::GrantFileAccessFromDropData(DropData* drop_data) {
- DCHECK_EQ(GetRoutingID(), drop_data->view_id);
- const int renderer_id = GetProcess()->GetID();
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
-#if defined(OS_CHROMEOS)
- // The externalfile:// scheme is used in Chrome OS to open external files in a
- // browser tab.
- if (drop_data->url.SchemeIs(content::kExternalFileScheme))
- policy->GrantRequestURL(renderer_id, drop_data->url);
-#endif
-
- // The filenames vector represents a capability to access the given files.
- storage::IsolatedContext::FileInfoSet files;
- for (auto& filename : drop_data->filenames) {
- // Make sure we have the same display_name as the one we register.
- if (filename.display_name.empty()) {
- std::string name;
- files.AddPath(filename.path, &name);
- filename.display_name = base::FilePath::FromUTF8Unsafe(name);
- } else {
- files.AddPathWithName(filename.path,
- filename.display_name.AsUTF8Unsafe());
- }
- // A dragged file may wind up as the value of an input element, or it
- // may be used as the target of a navigation instead. We don't know
- // which will happen at this point, so generously grant both access
- // and request permissions to the specific file to cover both cases.
- // We do not give it the permission to request all file:// URLs.
- policy->GrantRequestSpecificFileURL(renderer_id,
- net::FilePathToFileURL(filename.path));
-
- // If the renderer already has permission to read these paths, we don't need
- // to re-grant them. This prevents problems with DnD for files in the CrOS
- // file manager--the file manager already had read/write access to those
- // directories, but dragging a file would cause the read/write access to be
- // overwritten with read-only access, making them impossible to delete or
- // rename until the renderer was killed.
- if (!policy->CanReadFile(renderer_id, filename.path))
- policy->GrantReadFile(renderer_id, filename.path);
- }
-
- storage::IsolatedContext* isolated_context =
- storage::IsolatedContext::GetInstance();
- DCHECK(isolated_context);
-
- if (!files.fileset().empty()) {
- std::string filesystem_id =
- isolated_context->RegisterDraggedFileSystem(files);
- if (!filesystem_id.empty()) {
- // Grant the permission iff the ID is valid.
- policy->GrantReadFileSystem(renderer_id, filesystem_id);
- }
- drop_data->filesystem_id = base::UTF8ToUTF16(filesystem_id);
- }
-
- storage::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
- GetSiteInstance())
- ->GetFileSystemContext();
- for (auto& file_system_file : drop_data->file_system_files) {
- storage::FileSystemURL file_system_url =
- file_system_context->CrackURL(file_system_file.url);
-
- std::string register_name;
- std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
- file_system_url.type(), file_system_url.filesystem_id(),
- file_system_url.path(), &register_name);
-
- if (!filesystem_id.empty()) {
- // Grant the permission iff the ID is valid.
- policy->GrantReadFileSystem(renderer_id, filesystem_id);
- }
-
- // Note: We are using the origin URL provided by the sender here. It may be
- // different from the receiver's.
- file_system_file.url =
- GURL(storage::GetIsolatedFileSystemRootURIString(
- file_system_url.origin(), filesystem_id, std::string())
- .append(register_name));
- }
-}
-
} // namespace content
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 f8cce52869a..34bfe7e2a33 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -23,7 +23,6 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
#include "content/browser/site_instance_impl.h"
-#include "content/common/drag_event_source_info.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_view_host.h"
@@ -40,10 +39,7 @@ class SkBitmap;
namespace content {
class PageState;
-class RenderWidgetHostDelegate;
class SessionStorageNamespace;
-struct FileChooserFileInfo;
-struct FileChooserParams;
struct FrameReplicationState;
namespace mojom {
@@ -105,37 +101,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
int request_id,
const std::vector<base::FilePath>& files) override;
void DisableScrollbarsForThreshold(const gfx::Size& size) override;
- void DragSourceEndedAt(int client_x,
- int client_y,
- int screen_x,
- int screen_y,
- blink::WebDragOperation operation) override;
- void DragSourceSystemDragEnded() override;
- // |drop_data| must have been filtered. The embedder should call
- // FilterDropData before passing the drop data to RVHI.
- void DragTargetDragEnter(const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers) override;
- void DragTargetDragEnterWithMetaData(
- const std::vector<DropData::Metadata>& metadata,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers) override;
- void DragTargetDragOver(const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers) override;
- void DragTargetDragLeave() override;
- // |drop_data| must have been filtered. The embedder should call
- // FilterDropData before passing the drop data to RVHI.
- void DragTargetDrop(const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- int key_modifiers) override;
- void FilterDropData(DropData* drop_data) override;
void EnableAutoResize(const gfx::Size& min_size,
const gfx::Size& max_size) override;
void DisableAutoResize(const gfx::Size& new_size) override;
@@ -174,17 +139,16 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// Set up the RenderView child process. Virtual because it is overridden by
// TestRenderViewHost.
// The |opener_route_id| parameter indicates which RenderView created this
- // (MSG_ROUTING_NONE if none). If |max_page_id| is larger than -1, the
- // RenderView is told to start issuing page IDs at |max_page_id| + 1.
+ // (MSG_ROUTING_NONE if none).
// |window_was_created_with_opener| is true if this top-level frame was
// created with an opener. (The opener may have been closed since.)
// The |proxy_route_id| is only used when creating a RenderView in swapped out
- // state. |replicated_frame_state| contains replicated data for the
- // top-level frame, such as its name and sandbox flags.
+ // state.
+ // |replicated_frame_state| contains replicated data for the top-level frame,
+ // such as its name and sandbox flags.
virtual bool CreateRenderView(
int opener_frame_route_id,
int proxy_route_id,
- int32_t max_page_id,
const FrameReplicationState& replicated_frame_state,
bool window_was_created_with_opener);
@@ -287,7 +251,7 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void OnShowWidget(int route_id, const gfx::Rect& initial_rect);
void OnShowFullscreenWidget(int route_id);
void OnRenderProcessGone(int status, int error_code);
- void OnUpdateState(int32_t page_id, const PageState& state);
+ void OnUpdateState(const PageState& state);
void OnUpdateTargetURL(const GURL& url);
void OnClose();
void OnRequestMove(const gfx::Rect& pos);
@@ -295,18 +259,9 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
void OnPasteFromSelectionClipboard();
void OnRouteCloseEvent();
- void OnStartDragging(const DropData& drop_data,
- blink::WebDragOperationsMask operations_allowed,
- const SkBitmap& bitmap,
- const gfx::Vector2d& bitmap_offset_in_dip,
- const DragEventSourceInfo& event_info);
- void OnUpdateDragCursor(blink::WebDragOperation drag_operation);
void OnTakeFocus(bool reverse);
- void OnFocusedNodeChanged(bool is_editable_node,
- const gfx::Rect& node_bounds_in_viewport);
void OnClosePageACK();
void OnDidZoomURL(double zoom_level, const GURL& url);
- void OnFocusedNodeTouched(bool editable);
void OnFocus();
private:
@@ -335,12 +290,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// See https://crbug.com/304341.
WebPreferences ComputeWebkitPrefs();
- // 1. Grants permissions to URL (if any)
- // 2. Grants permissions to filenames
- // 3. Grants permissions to file system files.
- // 4. Register the files with the IsolatedContext.
- void GrantFileAccessFromDropData(DropData* drop_data);
-
// The RenderWidgetHost.
std::unique_ptr<RenderWidgetHostImpl> render_widget_host_;
@@ -359,11 +308,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// See BindingsPolicy for details.
int enabled_bindings_;
- // The most recent page ID we've heard from the renderer process. This is
- // used as context when other session history related IPCs arrive.
- // TODO(creis): Allocate this in WebContents/NavigationController instead.
- int32_t page_id_;
-
// Tracks whether this RenderViewHost is in an active state. False if the
// main frame is pending swap out, pending deletion, or swapped out, because
// it is not visible to the user in any of these cases.
@@ -389,9 +333,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// The termination status of the last render view that terminated.
base::TerminationStatus render_view_termination_status_;
- // True if the current focused element is editable.
- bool is_focused_element_editable_;
-
// This is updated every time UpdateWebkitPreferences is called. That method
// is in turn called when any of the settings change that the WebPreferences
// values depend on.
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 6e579595eff..725c9e5555e 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -70,7 +70,7 @@ class RenderViewHostTest : public RenderViewHostImplTestHarness {
// See RenderViewHost::OnNavigate for a discussion.
TEST_F(RenderViewHostTest, FilterAbout) {
main_test_rfh()->NavigateAndCommitRendererInitiated(
- 1, true, GURL("about:cache"));
+ true, GURL("about:cache"));
ASSERT_TRUE(controller().GetVisibleEntry());
EXPECT_EQ(GURL(url::kAboutBlankURL),
controller().GetVisibleEntry()->GetURL());
@@ -100,7 +100,8 @@ class MockDraggingRenderViewHostDelegateView
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override {
drag_url_ = drop_data.url;
html_base_url_ = drop_data.html_base_url;
}
@@ -173,9 +174,11 @@ TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
dropped_data.filenames.push_back(
ui::FileInfo(dragged_file_path, base::FilePath()));
- rvh()->FilterDropData(&dropped_data);
- rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point,
- blink::WebDragOperationNone, 0);
+ // TODO(paulmeyer): These will need to target the correct specific
+ // RenderWidgetHost to work with OOPIFs. See crbug.com/647249.
+ rvh()->GetWidget()->FilterDropData(&dropped_data);
+ rvh()->GetWidget()->DragTargetDragEnter(
+ dropped_data, client_point, screen_point, blink::WebDragOperationNone, 0);
int id = process()->GetID();
ChildProcessSecurityPolicyImpl* policy =
@@ -195,12 +198,12 @@ TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("foo");
EXPECT_EQ(0, process()->bad_msg_count());
- test_rvh()->TestOnUpdateStateWithFile(-1, file_path);
+ test_rvh()->TestOnUpdateStateWithFile(file_path);
EXPECT_EQ(1, process()->bad_msg_count());
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
process()->GetID(), file_path);
- test_rvh()->TestOnUpdateStateWithFile(-1, file_path);
+ test_rvh()->TestOnUpdateStateWithFile(file_path);
EXPECT_EQ(1, process()->bad_msg_count());
}
@@ -224,7 +227,7 @@ TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
main_test_rfh()->PrepareForCommit();
contents()->GetMainFrame()->SendNavigateWithModificationCallback(
- 1, 1, true, url, set_bad_file_path_callback);
+ 1, true, url, set_bad_file_path_callback);
EXPECT_EQ(1, process()->bad_msg_count());
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
@@ -232,7 +235,7 @@ TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
main_test_rfh()->PrepareForCommit();
contents()->GetMainFrame()->SendNavigateWithModificationCallback(
- 2, 2, true, url, set_bad_file_path_callback);
+ 2, true, url, set_bad_file_path_callback);
EXPECT_EQ(1, process()->bad_msg_count());
}
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index 4666f273437..c6b67367e33 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -26,12 +26,7 @@ namespace IPC {
class Message;
}
-namespace base {
-class TimeDelta;
-}
-
namespace content {
-class GpuProcessHost;
class ResourceDispatcherHostImpl;
class SessionStorageNamespace;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
index 6938610878a..ef0a9696c6e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "build/build_config.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
+
+#include "build/build_config.h"
+#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "ui/gfx/geometry/rect.h"
namespace content {
@@ -50,10 +52,10 @@ RenderWidgetHostImpl* RenderWidgetHostDelegate::GetFocusedRenderWidgetHost(
return receiving_widget;
}
-gfx::Rect RenderWidgetHostDelegate::GetRootWindowResizerRect(
- RenderWidgetHostImpl* render_widget_host) const {
- return gfx::Rect();
-};
+RenderWidgetHostImpl*
+RenderWidgetHostDelegate::GetRenderWidgetHostWithPageFocus() {
+ return nullptr;
+}
bool RenderWidgetHostDelegate::IsFullscreenForCurrentTab() const {
return false;
@@ -77,9 +79,17 @@ bool RenderWidgetHostDelegate::IsHidden() {
return false;
}
+RenderViewHostDelegateView* RenderWidgetHostDelegate::GetDelegateView() {
+ return nullptr;
+}
+
RenderWidgetHostImpl* RenderWidgetHostDelegate::GetFullscreenRenderWidgetHost()
const {
return nullptr;
}
+bool RenderWidgetHostDelegate::OnUpdateDragCursor() {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
index 724a3af8604..b9c236987fb 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -11,8 +11,12 @@
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "content/common/drag_event_source_info.h"
+#include "content/public/browser/renderer_unresponsive_type.h"
+#include "content/public/common/drop_data.h"
#include "third_party/WebKit/public/platform/WebDisplayMode.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebDragOperation.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/native_widget_types.h"
namespace blink {
@@ -31,6 +35,7 @@ namespace content {
class BrowserAccessibilityManager;
class RenderWidgetHostImpl;
class RenderWidgetHostInputEventRouter;
+class RenderViewHostDelegateView;
class TextInputManager;
struct ScreenInfo;
struct NativeWebKeyboardEvent;
@@ -140,20 +145,6 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
virtual RenderWidgetHostImpl* GetFocusedRenderWidgetHost(
RenderWidgetHostImpl* receiving_widget);
- // Used in histograms to differentiate between the different types of
- // renderer hang reported by RenderWidgetHostDelegate::RendererUnresponsive.
- // Only add values at the end, do not delete values.
- enum RendererUnresponsiveType {
- RENDERER_UNRESPONSIVE_UNKNOWN = 0,
- RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS = 1,
- RENDERER_UNRESPONSIVE_DIALOG_CLOSED = 2,
- RENDERER_UNRESPONSIVE_DIALOG_SUPPRESSED = 3,
- RENDERER_UNRESPONSIVE_BEFORE_UNLOAD = 4,
- RENDERER_UNRESPONSIVE_UNLOAD = 5,
- RENDERER_UNRESPONSIVE_CLOSE_PAGE = 6,
- RENDERER_UNRESPONSIVE_MAX = RENDERER_UNRESPONSIVE_CLOSE_PAGE,
- };
-
// Notification that the renderer has become unresponsive. The
// delegate can use this notification to show a warning to the user.
virtual void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host,
@@ -173,11 +164,6 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
bool last_unlocked_by_target,
bool privileged) {}
- // Return the rect where to display the resize corner, if any, otherwise
- // an empty rect.
- virtual gfx::Rect GetRootWindowResizerRect(
- RenderWidgetHostImpl* render_widget_host) const;
-
// Returns whether the associated tab is in fullscreen mode.
virtual bool IsFullscreenForCurrentTab() const;
@@ -222,11 +208,39 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// this RenderWidgetHost.
virtual bool IsHidden();
+ // Returns the associated RenderViewHostDelegateView*, if possible.
+ virtual RenderViewHostDelegateView* GetDelegateView();
+
// Returns the current Flash fullscreen RenderWidgetHostImpl if any. This is
// not intended for use with other types of fullscreen, such as HTML
// fullscreen, and will return nullptr for those cases.
virtual RenderWidgetHostImpl* GetFullscreenRenderWidgetHost() const;
+ // Allow the delegate to handle the cursor update. Returns true if handled.
+ virtual bool OnUpdateDragCursor();
+
+ // Inner WebContents Helpers -------------------------------------------------
+ //
+ // These functions are helpers in managing a hierharchy of WebContents
+ // involved in rendering inner WebContents.
+
+ // Get the RenderWidgetHost that should receive page level focus events. This
+ // will be the widget that is rendering the main frame of the currently
+ // focused WebContents.
+ virtual RenderWidgetHostImpl* GetRenderWidgetHostWithPageFocus();
+
+ // In cases with multiple RenderWidgetHosts involved in rendering a page, only
+ // one widget should be focused and active. This ensures that
+ // |render_widget_host| is focused and that its owning WebContents is also
+ // the focused WebContents.
+ virtual void FocusOwningWebContents(
+ RenderWidgetHostImpl* render_widget_host) {}
+
+ // Notifies the delegate that a focused editable element has been touched
+ // inside this RenderWidgetHost. If |editable| is true then the focused
+ // element accepts text input.
+ virtual void FocusedNodeTouched(bool editable) {}
+
protected:
virtual ~RenderWidgetHostDelegate() {}
};
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 6a05961dcff..2397e771f3e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -33,6 +33,7 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_metadata_util.h"
@@ -44,6 +45,8 @@
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -53,12 +56,14 @@
#include "content/common/content_constants_internal.h"
#include "content/common/content_switches_internal.h"
#include "content/common/cursors/webcursor.h"
+#include "content/common/drag_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/input_messages.h"
#include "content/common/resize_params.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -71,14 +76,19 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/ipc/common/gpu_messages.h"
+#include "net/base/filename_util.h"
#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 "ui/base/clipboard/clipboard.h"
+#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/snapshot/snapshot.h"
@@ -90,6 +100,8 @@
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebKeyboardEvent;
@@ -175,6 +187,56 @@ inline blink::WebGestureEvent CreateScrollEndForWrapping(
return wrap_gesture_scroll_end;
}
+std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
+ std::vector<DropData::Metadata> metadata;
+ if (!drop_data.text.is_null()) {
+ metadata.push_back(DropData::Metadata::CreateForMimeType(
+ DropData::Kind::STRING,
+ base::ASCIIToUTF16(ui::Clipboard::kMimeTypeText)));
+ }
+
+ if (drop_data.url.is_valid()) {
+ metadata.push_back(DropData::Metadata::CreateForMimeType(
+ DropData::Kind::STRING,
+ base::ASCIIToUTF16(ui::Clipboard::kMimeTypeURIList)));
+ }
+
+ if (!drop_data.html.is_null()) {
+ metadata.push_back(DropData::Metadata::CreateForMimeType(
+ DropData::Kind::STRING,
+ base::ASCIIToUTF16(ui::Clipboard::kMimeTypeHTML)));
+ }
+
+ // On Aura, filenames are available before drop.
+ for (const auto& file_info : drop_data.filenames) {
+ if (!file_info.path.empty()) {
+ metadata.push_back(DropData::Metadata::CreateForFilePath(file_info.path));
+ }
+ }
+
+ // On Android, only files' mime types are available before drop.
+ for (const auto& mime_type : drop_data.file_mime_types) {
+ if (!mime_type.empty()) {
+ metadata.push_back(DropData::Metadata::CreateForMimeType(
+ DropData::Kind::FILENAME, mime_type));
+ }
+ }
+
+ for (const auto& file_system_file : drop_data.file_system_files) {
+ if (!file_system_file.url.is_empty()) {
+ metadata.push_back(
+ DropData::Metadata::CreateForFileSystemUrl(file_system_file.url));
+ }
+ }
+
+ for (const auto& custom_data_item : drop_data.custom_data) {
+ metadata.push_back(DropData::Metadata::CreateForMimeType(
+ DropData::Kind::STRING, custom_data_item.first));
+ }
+
+ return metadata;
+}
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
@@ -204,7 +266,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
text_direction_updated_(false),
text_direction_(blink::WebTextDirectionLeftToRight),
text_direction_canceled_(false),
- suppress_next_char_events_(false),
+ suppress_events_until_keydown_(false),
pending_mouse_lock_request_(false),
allow_privileged_mouse_lock_(false),
has_touch_handler_(false),
@@ -217,7 +279,9 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
hung_renderer_delay_(
base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
hang_monitor_reason_(
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN),
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN),
+ hang_monitor_event_type_(blink::WebInputEvent::Undefined),
+ last_event_type_(blink::WebInputEvent::Undefined),
new_content_rendering_delay_(
base::TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
weak_factory_(this) {
@@ -338,12 +402,6 @@ void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
view_.reset();
}
- // If the renderer has not yet been initialized, then the surface ID
- // namespace will be sent during initialization.
- if (view_ && renderer_initialized_) {
- Send(new ViewMsg_SetFrameSinkId(routing_id_, view_->GetFrameSinkId()));
- }
-
synthetic_gesture_controller_.reset();
}
@@ -390,8 +448,8 @@ void RenderWidgetHostImpl::SendScreenRects() {
waiting_for_screen_rects_ack_ = true;
}
-void RenderWidgetHostImpl::SuppressNextCharEvents() {
- suppress_next_char_events_ = true;
+void RenderWidgetHostImpl::SuppressEventsUntilKeyDown() {
+ suppress_events_until_keydown_ = true;
}
void RenderWidgetHostImpl::FlushInput() {
@@ -410,12 +468,6 @@ void RenderWidgetHostImpl::Init() {
renderer_initialized_ = true;
- // If the RWHV has not yet been set, the surface ID namespace will get
- // passed down by the call to SetView().
- if (view_) {
- Send(new ViewMsg_SetFrameSinkId(routing_id_, view_->GetFrameSinkId()));
- }
-
SendScreenRects();
WasResized();
@@ -484,7 +536,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
OnShowDisambiguationPopup)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
@@ -494,6 +545,9 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardCompositorProto,
OnForwardCompositorProto)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames, OnSetNeedsBeginFrames)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
+ IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
+ IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -554,14 +608,7 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
is_hidden_ = false;
SendScreenRects();
-
- // When hidden, timeout monitoring for input events is disabled. Restore it
- // now to ensure consistent hang detection.
- if (in_flight_event_count_) {
- RestartHangMonitorTimeout();
- hang_monitor_reason_ =
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS;
- }
+ RestartHangMonitorTimeoutIfNecessary();
// Always repaint on restore.
bool needs_repainting = true;
@@ -599,7 +646,6 @@ bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
GetScreenInfo(&resize_params->screen_info);
if (delegate_) {
- resize_params->resizer_rect = delegate_->GetRootWindowResizerRect(this);
resize_params->is_fullscreen_granted =
delegate_->IsFullscreenForCurrentTab();
resize_params->display_mode = delegate_->GetDisplayMode(this);
@@ -615,8 +661,8 @@ bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
// ScaleToCeiledSize(new_size, device_scale_factor) ??
resize_params->physical_backing_size = view_->GetPhysicalBackingSize();
resize_params->top_controls_height = view_->GetTopControlsHeight();
- resize_params->top_controls_shrink_blink_size =
- view_->DoTopControlsShrinkBlinkSize();
+ resize_params->browser_controls_shrink_blink_size =
+ view_->DoBrowserControlsShrinkBlinkSize();
resize_params->bottom_controls_height = view_->GetBottomControlsHeight();
resize_params->visible_viewport_size = view_->GetVisibleViewportSize();
}
@@ -626,7 +672,8 @@ bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
old_resize_params_->new_size != resize_params->new_size ||
(old_resize_params_->physical_backing_size.IsEmpty() &&
!resize_params->physical_backing_size.IsEmpty());
- bool dirty = size_changed ||
+ bool dirty =
+ size_changed ||
old_resize_params_->screen_info != resize_params->screen_info ||
old_resize_params_->physical_backing_size !=
resize_params->physical_backing_size ||
@@ -635,8 +682,8 @@ bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
old_resize_params_->display_mode != resize_params->display_mode ||
old_resize_params_->top_controls_height !=
resize_params->top_controls_height ||
- old_resize_params_->top_controls_shrink_blink_size !=
- resize_params->top_controls_shrink_blink_size ||
+ old_resize_params_->browser_controls_shrink_blink_size !=
+ resize_params->browser_controls_shrink_blink_size ||
old_resize_params_->bottom_controls_height !=
resize_params->bottom_controls_height ||
old_resize_params_->visible_viewport_size !=
@@ -682,10 +729,6 @@ void RenderWidgetHostImpl::WasResized() {
delegate_->RenderWidgetWasResized(this, width_changed);
}
-void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
- Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
-}
-
void RenderWidgetHostImpl::GotFocus() {
Focus();
if (owner_delegate_)
@@ -695,34 +738,43 @@ void RenderWidgetHostImpl::GotFocus() {
}
void RenderWidgetHostImpl::Focus() {
- is_focused_ = true;
-
- Send(new InputMsg_SetFocus(routing_id_, true));
+ RenderWidgetHostImpl* focused_widget =
+ delegate_ ? delegate_->GetRenderWidgetHostWithPageFocus() : nullptr;
- // Also send page-level focus state to other SiteInstances involved in
- // rendering the current FrameTree.
- if (RenderViewHost::From(this) && delegate_)
- delegate_->ReplicatePageFocus(true);
+ if (!focused_widget)
+ focused_widget = this;
+ focused_widget->SetPageFocus(true);
}
void RenderWidgetHostImpl::Blur() {
- is_focused_ = false;
+ RenderWidgetHostImpl* focused_widget =
+ delegate_ ? delegate_->GetRenderWidgetHostWithPageFocus() : nullptr;
- // If there is a pending mouse lock request, we don't want to reject it at
- // this point. The user can switch focus back to this view and approve the
- // request later.
- if (IsMouseLocked())
- view_->UnlockMouse();
+ if (!focused_widget)
+ focused_widget = this;
+ focused_widget->SetPageFocus(false);
+}
- if (touch_emulator_)
- touch_emulator_->CancelTouch();
+void RenderWidgetHostImpl::SetPageFocus(bool focused) {
+ is_focused_ = focused;
+
+ if (!focused) {
+ // If there is a pending mouse lock request, we don't want to reject it at
+ // this point. The user can switch focus back to this view and approve the
+ // request later.
+ if (IsMouseLocked())
+ view_->UnlockMouse();
+
+ if (touch_emulator_)
+ touch_emulator_->CancelTouch();
+ }
- Send(new InputMsg_SetFocus(routing_id_, false));
+ Send(new InputMsg_SetFocus(routing_id_, focused));
// Also send page-level focus state to other SiteInstances involved in
// rendering the current FrameTree.
if (RenderViewHost::From(this) && delegate_)
- delegate_->ReplicatePageFocus(false);
+ delegate_->ReplicatePageFocus(focused);
}
void RenderWidgetHostImpl::LostCapture() {
@@ -907,16 +959,28 @@ bool RenderWidgetHostImpl::ScheduleComposite() {
void RenderWidgetHostImpl::StartHangMonitorTimeout(
base::TimeDelta delay,
- RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason) {
+ blink::WebInputEvent::Type event_type,
+ RendererUnresponsiveType hang_monitor_reason) {
if (!hang_monitor_timeout_)
return;
+ if (!hang_monitor_timeout_->IsRunning())
+ hang_monitor_event_type_ = event_type;
+ last_event_type_ = event_type;
hang_monitor_timeout_->Start(delay);
hang_monitor_reason_ = hang_monitor_reason;
}
-void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
- if (hang_monitor_timeout_)
+void RenderWidgetHostImpl::RestartHangMonitorTimeoutIfNecessary() {
+ if (!hang_monitor_timeout_)
+ return;
+ if (in_flight_event_count_ > 0 && !is_hidden_) {
+ if (hang_monitor_reason_ ==
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN) {
+ hang_monitor_reason_ =
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS;
+ }
hang_monitor_timeout_->Restart(hung_renderer_delay_);
+ }
}
void RenderWidgetHostImpl::DisableHangMonitorForTesting() {
@@ -928,7 +992,7 @@ void RenderWidgetHostImpl::StopHangMonitorTimeout() {
if (hang_monitor_timeout_) {
hang_monitor_timeout_->Stop();
hang_monitor_reason_ =
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN;
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN;
}
RendererIsResponsive();
}
@@ -957,7 +1021,8 @@ void RenderWidgetHostImpl::OnFirstPaintAfterLoad() {
}
void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
- ForwardMouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo());
+ ForwardMouseEventWithLatencyInfo(mouse_event,
+ ui::LatencyInfo(ui::SourceEventType::OTHER));
if (owner_delegate_)
owner_delegate_->RenderWidgetDidForwardMouseEvent(mouse_event);
}
@@ -986,7 +1051,8 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
void RenderWidgetHostImpl::ForwardWheelEvent(
const WebMouseWheelEvent& wheel_event) {
- ForwardWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo());
+ ForwardWheelEventWithLatencyInfo(wheel_event,
+ ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
@@ -1013,7 +1079,10 @@ void RenderWidgetHostImpl::ForwardEmulatedGestureEvent(
void RenderWidgetHostImpl::ForwardGestureEvent(
const blink::WebGestureEvent& gesture_event) {
- ForwardGestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo());
+ ForwardGestureEventWithLatencyInfo(
+ gesture_event,
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
+ gesture_event));
}
void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
@@ -1052,7 +1121,9 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
// Bubble to test the resending logic of gesture events.
if (scroll_update_needs_wrapping) {
ForwardGestureEventWithLatencyInfo(
- CreateScrollBeginForWrapping(gesture_event), ui::LatencyInfo());
+ CreateScrollBeginForWrapping(gesture_event),
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
+ gesture_event));
}
// Delegate must be non-null, due to |ShouldDropInputEvents()| test.
@@ -1066,15 +1137,17 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
if (scroll_update_needs_wrapping) {
ForwardGestureEventWithLatencyInfo(
- CreateScrollEndForWrapping(gesture_event), ui::LatencyInfo());
+ CreateScrollEndForWrapping(gesture_event),
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
+ gesture_event));
}
}
void RenderWidgetHostImpl::ForwardEmulatedTouchEvent(
const blink::WebTouchEvent& touch_event) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardEmulatedTouchEvent");
-
- TouchEventWithLatencyInfo touch_with_latency(touch_event);
+ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
+ TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
DispatchInputEventWithLatencyInfo(touch_event, &touch_with_latency.latency);
input_router_->SendTouchEvent(touch_with_latency);
}
@@ -1118,10 +1191,10 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
// First, let keypress listeners take a shot at handling the event. If a
// listener handles the event, it should not be propagated to the renderer.
if (KeyPressListenersHandleEvent(key_event)) {
- // Some keypresses that are accepted by the listener might have follow up
- // char events, which should be ignored.
+ // Some keypresses that are accepted by the listener may be followed by Char
+ // and KeyUp events, which should be ignored.
if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = true;
+ suppress_events_until_keydown_ = true;
return;
}
@@ -1130,27 +1203,28 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
if (!WebInputEvent::isKeyboardEventType(key_event.type))
return;
- if (suppress_next_char_events_) {
- // If preceding RawKeyDown event was handled by the browser, then we need
- // suppress all Char events generated by it. Please note that, one
- // RawKeyDown event may generate multiple Char events, so we can't reset
- // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
- if (key_event.type == WebKeyboardEvent::Char)
+ if (suppress_events_until_keydown_) {
+ // If the preceding RawKeyDown event was handled by the browser, then we
+ // need to suppress all events generated by it until the next RawKeyDown or
+ // KeyDown event.
+ if (key_event.type == WebKeyboardEvent::KeyUp ||
+ key_event.type == WebKeyboardEvent::Char)
return;
- // We get a KeyUp or a RawKeyDown event.
- suppress_next_char_events_ = false;
+ DCHECK(key_event.type == WebKeyboardEvent::RawKeyDown ||
+ key_event.type == WebKeyboardEvent::KeyDown);
+ suppress_events_until_keydown_ = false;
}
bool is_shortcut = false;
// Only pre-handle the key event if it's not handled by the input method.
if (delegate_ && !key_event.skip_in_browser) {
- // We need to set |suppress_next_char_events_| to true if
+ // We need to set |suppress_events_until_keydown_| to true if
// PreHandleKeyboardEvent() returns true, but |this| may already be
- // destroyed at that time. So set |suppress_next_char_events_| true here,
- // then revert it afterwards when necessary.
+ // destroyed at that time. So set |suppress_events_until_keydown_| true
+ // here, then revert it afterwards when necessary.
if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = true;
+ suppress_events_until_keydown_ = true;
// Tab switching/closing accelerators aren't sent to the renderer to avoid
// a hung/malicious renderer from interfering.
@@ -1158,13 +1232,14 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
return;
if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = false;
+ suppress_events_until_keydown_ = false;
}
if (touch_emulator_ && touch_emulator_->HandleKeyboardEvent(key_event))
return;
-
- NativeWebKeyboardEventWithLatencyInfo key_event_with_latency(key_event);
+ ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
+ NativeWebKeyboardEventWithLatencyInfo key_event_with_latency(key_event,
+ latency_info);
key_event_with_latency.event.isBrowserShortcut = is_shortcut;
DispatchInputEventWithLatencyInfo(key_event, &key_event_with_latency.latency);
input_router_->SendKeyboardEvent(key_event_with_latency);
@@ -1269,6 +1344,75 @@ void RenderWidgetHostImpl::HandleCompositorProto(
Send(new ViewMsg_HandleCompositorProto(GetRoutingID(), proto));
}
+void RenderWidgetHostImpl::DragTargetDragEnter(
+ const DropData& drop_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ WebDragOperationsMask operations_allowed,
+ int key_modifiers) {
+ DragTargetDragEnterWithMetaData(DropDataToMetaData(drop_data), client_pt,
+ screen_pt, operations_allowed, key_modifiers);
+}
+
+void RenderWidgetHostImpl::DragTargetDragEnterWithMetaData(
+ const std::vector<DropData::Metadata>& metadata,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ WebDragOperationsMask operations_allowed,
+ int key_modifiers) {
+ Send(new DragMsg_TargetDragEnter(GetRoutingID(), metadata, client_pt,
+ screen_pt, operations_allowed,
+ key_modifiers));
+}
+
+void RenderWidgetHostImpl::DragTargetDragOver(
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ WebDragOperationsMask operations_allowed,
+ int key_modifiers) {
+ Send(new DragMsg_TargetDragOver(GetRoutingID(), client_pt, screen_pt,
+ operations_allowed, key_modifiers));
+}
+
+void RenderWidgetHostImpl::DragTargetDragLeave() {
+ Send(new DragMsg_TargetDragLeave(GetRoutingID()));
+}
+
+void RenderWidgetHostImpl::DragTargetDrop(const DropData& drop_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ int key_modifiers) {
+ DropData drop_data_with_permissions(drop_data);
+ GrantFileAccessFromDropData(&drop_data_with_permissions);
+ Send(new DragMsg_TargetDrop(GetRoutingID(), drop_data_with_permissions,
+ client_pt, screen_pt, key_modifiers));
+}
+
+void RenderWidgetHostImpl::DragSourceEndedAt(
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperation operation) {
+ Send(new DragMsg_SourceEnded(GetRoutingID(),
+ client_pt,
+ screen_pt,
+ operation));
+}
+
+void RenderWidgetHostImpl::DragSourceSystemDragEnded() {
+ Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
+}
+
+void RenderWidgetHostImpl::FilterDropData(DropData* drop_data) {
+#if DCHECK_IS_ON()
+ drop_data->view_id = GetRoutingID();
+#endif // DCHECK_IS_ON()
+
+ GetProcess()->FilterURL(true, &drop_data->url);
+ if (drop_data->did_originate_from_renderer) {
+ drop_data->filenames.clear();
+ }
+}
+
void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
if (delegate_)
delegate_->ScreenInfoChanged();
@@ -1308,9 +1452,9 @@ const NativeWebKeyboardEvent*
return input_router_->GetLastKeyboardEvent();
}
-void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
- uint32_t offset,
- const gfx::Range& range) {
+void RenderWidgetHostImpl::SelectionChanged(const base::string16& text,
+ uint32_t offset,
+ const gfx::Range& range) {
if (view_)
view_->SelectionChanged(text, static_cast<size_t>(offset), range);
}
@@ -1337,6 +1481,72 @@ void RenderWidgetHostImpl::OnSetNeedsBeginFrames(bool needs_begin_frames) {
view_->SetNeedsBeginFrames(needs_begin_frames);
}
+void RenderWidgetHostImpl::OnFocusedNodeTouched(bool editable) {
+ if (delegate_)
+ delegate_->FocusedNodeTouched(editable);
+}
+
+void RenderWidgetHostImpl::OnStartDragging(
+ const DropData& drop_data,
+ blink::WebDragOperationsMask drag_operations_mask,
+ const SkBitmap& bitmap,
+ const gfx::Vector2d& bitmap_offset_in_dip,
+ const DragEventSourceInfo& event_info) {
+ RenderViewHostDelegateView* view = delegate_->GetDelegateView();
+ if (!view) {
+ // Need to clear drag and drop state in blink.
+ DragSourceSystemDragEnded();
+ return;
+ }
+
+ DropData filtered_data(drop_data);
+ RenderProcessHost* process = GetProcess();
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+
+ // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
+ if (!filtered_data.url.SchemeIs(url::kJavaScriptScheme))
+ process->FilterURL(true, &filtered_data.url);
+ process->FilterURL(false, &filtered_data.html_base_url);
+ // Filter out any paths that the renderer didn't have access to. This prevents
+ // the following attack on a malicious renderer:
+ // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
+ // doesn't have read permissions for.
+ // 2. We initiate a native DnD operation.
+ // 3. DnD operation immediately ends since mouse is not held down. DnD events
+ // still fire though, which causes read permissions to be granted to the
+ // renderer for any file paths in the drop.
+ filtered_data.filenames.clear();
+ for (const auto& file_info : drop_data.filenames) {
+ if (policy->CanReadFile(GetProcess()->GetID(), file_info.path))
+ filtered_data.filenames.push_back(file_info);
+ }
+
+ storage::FileSystemContext* file_system_context =
+ GetProcess()->GetStoragePartition()->GetFileSystemContext();
+ filtered_data.file_system_files.clear();
+ for (size_t i = 0; i < drop_data.file_system_files.size(); ++i) {
+ storage::FileSystemURL file_system_url =
+ file_system_context->CrackURL(drop_data.file_system_files[i].url);
+ if (policy->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url))
+ filtered_data.file_system_files.push_back(drop_data.file_system_files[i]);
+ }
+
+ float scale = GetScaleFactorForView(GetView());
+ gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale));
+ view->StartDragging(filtered_data, drag_operations_mask, image,
+ bitmap_offset_in_dip, event_info, this);
+}
+
+void RenderWidgetHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
+ if (delegate_ && delegate_->OnUpdateDragCursor())
+ return;
+
+ RenderViewHostDelegateView* view = delegate_->GetDelegateView();
+ if (view)
+ view->UpdateDragCursor(current_op);
+}
+
void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
int exit_code) {
if (!renderer_initialized_)
@@ -1349,7 +1559,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
waiting_for_screen_rects_ack_ = false;
// Must reset these to ensure that keyboard events work with a new renderer.
- suppress_next_char_events_ = false;
+ suppress_events_until_keydown_ = false;
// Reset some fields in preparation for recovering from a crash.
ResetSizeAndRepaintPendingFlags();
@@ -1492,10 +1702,9 @@ void RenderWidgetHostImpl::RendererIsUnresponsive() {
Source<RenderWidgetHost>(this),
NotificationService::NoDetails());
is_unresponsive_ = true;
- RenderWidgetHostDelegate::RendererUnresponsiveType reason =
- hang_monitor_reason_;
+ RendererUnresponsiveType reason = hang_monitor_reason_;
hang_monitor_reason_ =
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN;
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN;
if (delegate_)
delegate_->RendererUnresponsive(this, reason);
@@ -1876,37 +2085,43 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
if (!process_->HasConnection())
return INPUT_EVENT_ACK_STATE_UNKNOWN;
- if (delegate_ && (event.type == WebInputEvent::MouseDown ||
- event.type == WebInputEvent::GestureScrollBegin ||
- event.type == WebInputEvent::GestureTapDown ||
- event.type == WebInputEvent::RawKeyDown)) {
- delegate_->OnUserInteraction(this, event.type);
+ if (delegate_) {
+ if (event.type == WebInputEvent::MouseDown ||
+ event.type == WebInputEvent::TouchStart) {
+ delegate_->FocusOwningWebContents(this);
+ }
+ if (event.type == WebInputEvent::MouseDown ||
+ event.type == WebInputEvent::GestureScrollBegin ||
+ event.type == WebInputEvent::TouchStart ||
+ event.type == WebInputEvent::RawKeyDown) {
+ delegate_->OnUserInteraction(this, event.type);
+ }
}
return view_ ? view_->FilterInputEvent(event)
: INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
-void RenderWidgetHostImpl::IncrementInFlightEventCount() {
+void RenderWidgetHostImpl::IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) {
increment_in_flight_event_count();
if (!is_hidden_) {
StartHangMonitorTimeout(
- hung_renderer_delay_,
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS);
+ hung_renderer_delay_, event_type,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS);
}
}
-void RenderWidgetHostImpl::DecrementInFlightEventCount() {
+void RenderWidgetHostImpl::DecrementInFlightEventCount(
+ InputEventAckSource ack_source) {
if (decrement_in_flight_event_count() <= 0) {
// Cancel pending hung renderer checks since the renderer is responsive.
StopHangMonitorTimeout();
} else {
- // The renderer is responsive, but there are in-flight events to wait for.
- if (!is_hidden_) {
- RestartHangMonitorTimeout();
- hang_monitor_reason_ =
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS;
- }
+ // Only restart the hang monitor timer if we got a response from the
+ // main thread.
+ if (ack_source == InputEventAckSource::MAIN_THREAD)
+ RestartHangMonitorTimeoutIfNecessary();
}
}
@@ -1934,8 +2149,8 @@ void RenderWidgetHostImpl::DispatchInputEventWithLatencyInfo(
const blink::WebInputEvent& event,
ui::LatencyInfo* latency) {
latency_tracker_.OnInputEvent(event, latency);
- FOR_EACH_OBSERVER(InputEventObserver, input_event_observers_,
- OnInputEvent(event));
+ for (auto& observer : input_event_observers_)
+ observer.OnInputEvent(event);
}
void RenderWidgetHostImpl::OnKeyboardEventAck(
@@ -2006,7 +2221,7 @@ void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
if (type == BAD_ACK_MESSAGE) {
bad_message::ReceivedBadMessage(process_, bad_message::RWH_BAD_ACK_MESSAGE);
} else if (type == UNEXPECTED_EVENT_TYPE) {
- suppress_next_char_events_ = false;
+ suppress_events_until_keydown_ = false;
}
}
@@ -2216,4 +2431,87 @@ BrowserAccessibilityManager*
delegate_->GetOrCreateRootBrowserAccessibilityManager() : NULL;
}
+void RenderWidgetHostImpl::GrantFileAccessFromDropData(DropData* drop_data) {
+ DCHECK_EQ(GetRoutingID(), drop_data->view_id);
+ const int renderer_id = GetProcess()->GetID();
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+
+#if defined(OS_CHROMEOS)
+ // The externalfile:// scheme is used in Chrome OS to open external files in a
+ // browser tab.
+ if (drop_data->url.SchemeIs(content::kExternalFileScheme))
+ policy->GrantRequestURL(renderer_id, drop_data->url);
+#endif
+
+ // The filenames vector represents a capability to access the given files.
+ storage::IsolatedContext::FileInfoSet files;
+ for (auto& filename : drop_data->filenames) {
+ // Make sure we have the same display_name as the one we register.
+ if (filename.display_name.empty()) {
+ std::string name;
+ files.AddPath(filename.path, &name);
+ filename.display_name = base::FilePath::FromUTF8Unsafe(name);
+ } else {
+ files.AddPathWithName(filename.path,
+ filename.display_name.AsUTF8Unsafe());
+ }
+ // A dragged file may wind up as the value of an input element, or it
+ // may be used as the target of a navigation instead. We don't know
+ // which will happen at this point, so generously grant both access
+ // and request permissions to the specific file to cover both cases.
+ // We do not give it the permission to request all file:// URLs.
+ policy->GrantRequestSpecificFileURL(renderer_id,
+ net::FilePathToFileURL(filename.path));
+
+ // If the renderer already has permission to read these paths, we don't need
+ // to re-grant them. This prevents problems with DnD for files in the CrOS
+ // file manager--the file manager already had read/write access to those
+ // directories, but dragging a file would cause the read/write access to be
+ // overwritten with read-only access, making them impossible to delete or
+ // rename until the renderer was killed.
+ if (!policy->CanReadFile(renderer_id, filename.path))
+ policy->GrantReadFile(renderer_id, filename.path);
+ }
+
+ storage::IsolatedContext* isolated_context =
+ storage::IsolatedContext::GetInstance();
+ DCHECK(isolated_context);
+
+ if (!files.fileset().empty()) {
+ std::string filesystem_id =
+ isolated_context->RegisterDraggedFileSystem(files);
+ if (!filesystem_id.empty()) {
+ // Grant the permission iff the ID is valid.
+ policy->GrantReadFileSystem(renderer_id, filesystem_id);
+ }
+ drop_data->filesystem_id = base::UTF8ToUTF16(filesystem_id);
+ }
+
+ storage::FileSystemContext* file_system_context =
+ GetProcess()->GetStoragePartition()->GetFileSystemContext();
+ for (auto& file_system_file : drop_data->file_system_files) {
+ storage::FileSystemURL file_system_url =
+ file_system_context->CrackURL(file_system_file.url);
+
+ std::string register_name;
+ std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
+ file_system_url.type(), file_system_url.filesystem_id(),
+ file_system_url.path(), &register_name);
+
+ if (!filesystem_id.empty()) {
+ // Grant the permission iff the ID is valid.
+ policy->GrantReadFileSystem(renderer_id, filesystem_id);
+ }
+
+ // Note: We are using the origin URL provided by the sender here. It may be
+ // different from the receiver's.
+ file_system_file.url =
+ GURL(storage::GetIsolatedFileSystemRootURIString(
+ file_system_url.origin(), filesystem_id, std::string())
+ .append(register_name));
+ file_system_file.filesystem_id = filesystem_id;
+ }
+}
+
} // 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 54962187523..8c17eef9be6 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -33,12 +33,14 @@
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/common/drag_event_source_info.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/synthetic_gesture_packet.h"
#include "content/common/view_message_enums.h"
#include "content/public/browser/readback_types.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 "third_party/WebKit/public/platform/WebDisplayMode.h"
#include "ui/base/ime/text_input_mode.h"
@@ -57,17 +59,10 @@ class RefCountedBytes;
namespace blink {
class WebInputEvent;
-#if defined(OS_ANDROID)
-class WebLayer;
-#endif
class WebMouseEvent;
struct WebCompositionUnderline;
}
-namespace cc {
-class CompositorFrameAck;
-}
-
#if defined(OS_MACOSX)
namespace device {
class PowerSaveBlocker;
@@ -165,8 +160,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
int GetRoutingID() const override;
RenderWidgetHostViewBase* GetView() const override;
bool IsLoading() const override;
- void ResizeRectChanged(const gfx::Rect& new_rect) override;
- void RestartHangMonitorTimeout() override;
+ void RestartHangMonitorTimeoutIfNecessary() override;
void DisableHangMonitorForTesting() override;
void SetIgnoreInputEvents(bool ignore_input_events) override;
void WasResized() override;
@@ -181,6 +175,35 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
RenderWidgetHost::InputEventObserver* observer) override;
void GetScreenInfo(content::ScreenInfo* result) override;
void HandleCompositorProto(const std::vector<uint8_t>& proto) override;
+ // |drop_data| must have been filtered. The embedder should call
+ // FilterDropData before passing the drop data to RWHI.
+ void DragTargetDragEnter(const DropData& drop_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers) override;
+ void DragTargetDragEnterWithMetaData(
+ const std::vector<DropData::Metadata>& metadata,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers) override;
+ void DragTargetDragOver(const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers) override;
+ void DragTargetDragLeave() override;
+ // |drop_data| must have been filtered. The embedder should call
+ // FilterDropData before passing the drop data to RWHI.
+ void DragTargetDrop(const DropData& drop_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ int key_modifiers) override;
+ void DragSourceEndedAt(const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperation operation) override;
+ void DragSourceSystemDragEnded() override;
+ void FilterDropData(DropData* drop_data) override;
// Notification that the screen info has changed.
void NotifyScreenInfoChanged();
@@ -251,6 +274,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// but it failed, thus HasFocus() returns false.
bool is_focused() const { return is_focused_; }
+ // Support for focus tracking on multi-WebContents cases. This will notify all
+ // renderers involved in a page about a page-level focus update. Users other
+ // than WebContents and RenderWidgetHost should use Focus()/Blur().
+ void SetPageFocus(bool focused);
+
// Called to notify the RenderWidget that it has lost the mouse lock.
void LostMouseLock();
@@ -293,9 +321,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// Starts a hang monitor timeout. If there's already a hang monitor timeout
// the new one will only fire if it has a shorter delay than the time
// left on the existing timeouts.
- void StartHangMonitorTimeout(
- base::TimeDelta delay,
- RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason);
+ void StartHangMonitorTimeout(base::TimeDelta delay,
+ blink::WebInputEvent::Type event_type,
+ RendererUnresponsiveType hang_monitor_reason);
// Stops all existing hang monitor timeouts and assumes the renderer is
// responsive.
@@ -316,15 +344,15 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& ui_latency) override;
- void ForwardTouchEventWithLatencyInfo(
+ virtual void ForwardTouchEventWithLatencyInfo(
const blink::WebTouchEvent& touch_event,
- const ui::LatencyInfo& ui_latency);
+ const ui::LatencyInfo& ui_latency); // Virtual for testing.
void ForwardMouseEventWithLatencyInfo(
const blink::WebMouseEvent& mouse_event,
const ui::LatencyInfo& ui_latency);
virtual void ForwardWheelEventWithLatencyInfo(
const blink::WebMouseWheelEvent& wheel_event,
- const ui::LatencyInfo& ui_latency); // Virtual for testing.
+ const ui::LatencyInfo& ui_latency); // Virtual for testing.
// Enables/disables touch emulation using mouse event. See TouchEmulator.
void SetTouchEventEmulationEnabled(
@@ -448,9 +476,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// Update the renderer's cache of the screen rect of the view and window.
void SendScreenRects();
- // Suppreses future char events until a keydown. See
- // suppress_next_char_events_.
- void SuppressNextCharEvents();
+ // Suppresses Char and KeyUp events until the next (Raw)KeyDown. See
+ // suppress_events_until_keydown_.
+ void SuppressEventsUntilKeyDown();
// Called by the view in response to a flush request.
void FlushInput();
@@ -519,6 +547,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// a new renderer is created.
void RendererExited(base::TerminationStatus status, int exit_code);
+ // Called from a RenderFrameHost when the text selection has changed.
+ void SelectionChanged(const base::string16& text,
+ uint32_t offset,
+ const gfx::Range& range);
+
// Expose increment/decrement of the in-flight event count, so
// RenderViewHostImpl can account for in-flight beforeunload/unload events.
int increment_in_flight_event_count() { return ++in_flight_event_count_; }
@@ -527,10 +560,22 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
return --in_flight_event_count_;
}
+ size_t in_flight_event_count() const { return in_flight_event_count_; }
+ blink::WebInputEvent::Type hang_monitor_event_type() const {
+ return hang_monitor_event_type_;
+ }
+ blink::WebInputEvent::Type last_event_type() const {
+ return last_event_type_;
+ }
+
bool renderer_initialized() const { return renderer_initialized_; }
bool needs_begin_frames() const { return needs_begin_frames_; }
+ base::WeakPtr<RenderWidgetHostImpl> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
protected:
// ---------------------------------------------------------------------------
// The following method is overridden by RenderViewHost to send upwards to
@@ -553,6 +598,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
private:
friend class MockRenderWidgetHost;
+ friend class TestRenderViewHost;
// Tell this object to destroy itself. If |also_delete| is specified, the
// destructor is called as well.
@@ -594,14 +640,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
const gfx::Size& size,
const cc::SharedBitmapId& id);
- void OnSelectionChanged(const base::string16& text,
- uint32_t offset,
- const gfx::Range& range);
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnForwardCompositorProto(const std::vector<uint8_t>& proto);
void OnSetNeedsBeginFrames(bool needs_begin_frames);
void OnHittestData(const FrameHostMsg_HittestData_Params& params);
+ void OnFocusedNodeTouched(bool editable);
+ void OnStartDragging(const DropData& drop_data,
+ blink::WebDragOperationsMask operations_allowed,
+ const SkBitmap& bitmap,
+ const gfx::Vector2d& bitmap_offset_in_dip,
+ const DragEventSourceInfo& event_info);
+ void OnUpdateDragCursor(blink::WebDragOperation current_op);
// Called (either immediately or asynchronously) after we're done with our
// BackingStore and can send an ACK to the renderer so it can paint onto it
@@ -617,8 +667,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
InputEventAckState FilterInputEvent(
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency_info) override;
- void IncrementInFlightEventCount() override;
- void DecrementInFlightEventCount() override;
+ void IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) override;
+ void DecrementInFlightEventCount(InputEventAckSource ack_source) override;
void OnHasTouchEventHandlers(bool has_handlers) override;
void DidFlush() override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
@@ -657,6 +708,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
int snapshot_id,
scoped_refptr<base::RefCountedBytes> png_data);
+ // 1. Grants permissions to URL (if any)
+ // 2. Grants permissions to filenames
+ // 3. Grants permissions to file system files.
+ // 4. Register the files with the IsolatedContext.
+ void GrantFileAccessFromDropData(DropData* drop_data);
+
// true if a renderer has once been valid. We use this flag to display a sad
// tab only when we lose our renderer and not if a paint occurs during
// initialization.
@@ -757,20 +814,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// NotifyTextDirection().
bool text_direction_canceled_;
- // Indicates if the next sequence of Char events should be suppressed or not.
- // System may translate a RawKeyDown event into zero or more Char events,
- // usually we send them to the renderer directly in sequence. However, If a
- // RawKeyDown event was not handled by the renderer but was handled by
- // our UnhandledKeyboardEvent() method, e.g. as an accelerator key, then we
- // shall not send the following sequence of Char events, which was generated
- // by this RawKeyDown event, to the renderer. Otherwise the renderer may
- // handle the Char events and cause unexpected behavior.
- // For example, pressing alt-2 may let the browser switch to the second tab,
- // but the Char event generated by alt-2 may also activate a HTML element
- // if its accesskey happens to be "2", then the user may get confused when
- // switching back to the original tab, because the content may already be
- // changed.
- bool suppress_next_char_events_;
+ // Indicates if Char and KeyUp events should be suppressed or not. Usually all
+ // events are sent to the renderer directly in sequence. However, if a
+ // RawKeyDown event was handled by PreHandleKeyboardEvent() or
+ // KeyPressListenersHandleEvent(), e.g. as an accelerator key, then the
+ // RawKeyDown event is not sent to the renderer, and the following sequence of
+ // Char and KeyUp events should also not be sent. Otherwise the renderer will
+ // see only the Char and KeyUp events and cause unexpected behavior. For
+ // example, pressing alt-2 may let the browser switch to the second tab, but
+ // the Char event generated by alt-2 may also activate a HTML element if its
+ // accesskey happens to be "2", then the user may get confused when switching
+ // back to the original tab, because the content may already have changed.
+ bool suppress_events_until_keydown_;
bool pending_mouse_lock_request_;
bool allow_privileged_mouse_lock_;
@@ -835,7 +890,13 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// Stores the reason the hang_monitor_timeout_ has been started. Used to
// report histograms if the renderer is hung.
- RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason_;
+ RendererUnresponsiveType hang_monitor_reason_;
+
+ // Type of the last blocking event that started the hang monitor.
+ blink::WebInputEvent::Type hang_monitor_event_type_;
+
+ // Type of the last blocking event sent to the renderer.
+ blink::WebInputEvent::Type last_event_type_;
// This value indicates how long to wait for a new compositor frame from a
// renderer process before clearing any previously displayed content.
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 132fa29ff11..f036a77d159 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
@@ -12,10 +12,12 @@
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.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/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/frame_messages.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "ui/events/blink/web_input_event_traits.h"
namespace {
@@ -169,7 +171,8 @@ RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
void RenderWidgetHostInputEventRouter::RouteMouseEvent(
RenderWidgetHostViewBase* root_view,
- blink::WebMouseEvent* event) {
+ blink::WebMouseEvent* event,
+ const ui::LatencyInfo& latency) {
RenderWidgetHostViewBase* target;
gfx::Point transformed_point;
const int mouse_button_modifiers = blink::WebInputEvent::LeftButtonDown |
@@ -180,8 +183,9 @@ void RenderWidgetHostInputEventRouter::RouteMouseEvent(
(event->type == blink::WebInputEvent::MouseUp ||
event->modifiers & mouse_button_modifiers)) {
target = mouse_capture_target_.target;
- transformed_point = root_view->TransformPointToCoordSpaceForView(
- gfx::Point(event->x, event->y), target);
+ if (!root_view->TransformPointToCoordSpaceForView(
+ gfx::Point(event->x, event->y), target, &transformed_point))
+ return;
if (event->type == blink::WebInputEvent::MouseUp)
mouse_capture_target_.target = nullptr;
} else {
@@ -194,7 +198,29 @@ void RenderWidgetHostInputEventRouter::RouteMouseEvent(
// the embedding renderer and then BrowserPluginGuest.
if (target && target->IsRenderWidgetHostViewGuest()) {
ui::LatencyInfo latency_info;
- root_view->ProcessMouseEvent(*event, latency_info);
+ RenderWidgetHostViewBase* owner_view =
+ static_cast<RenderWidgetHostViewGuest*>(target)
+ ->GetOwnerRenderWidgetHostView();
+ // In case there is nested RenderWidgetHostViewGuests (i.e., PDF inside
+ // <webview>), we will need the owner view of the top-most guest for input
+ // routing.
+ while (owner_view->IsRenderWidgetHostViewGuest()) {
+ owner_view = static_cast<RenderWidgetHostViewGuest*>(owner_view)
+ ->GetOwnerRenderWidgetHostView();
+ }
+
+ if (owner_view != root_view) {
+ // This happens when the view is embedded inside a cross-process frame
+ // (i.e., owner view is a RenderWidgetHostViewChildFrame).
+ gfx::Point owner_point;
+ if (!root_view->TransformPointToCoordSpaceForView(
+ gfx::Point(event->x, event->y), owner_view, &owner_point)) {
+ return;
+ }
+ event->x = owner_point.x();
+ event->y = owner_point.y();
+ }
+ owner_view->ProcessMouseEvent(*event, latency_info);
return;
}
@@ -214,15 +240,13 @@ void RenderWidgetHostInputEventRouter::RouteMouseEvent(
event->x = transformed_point.x();
event->y = transformed_point.y();
- // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
- // https://crbug.com/613628
- ui::LatencyInfo latency_info;
- target->ProcessMouseEvent(*event, latency_info);
+ target->ProcessMouseEvent(*event, latency);
}
void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
RenderWidgetHostViewBase* root_view,
- blink::WebMouseWheelEvent* event) {
+ blink::WebMouseWheelEvent* event,
+ const ui::LatencyInfo& latency) {
gfx::Point transformed_point;
RenderWidgetHostViewBase* target = FindEventTarget(
root_view, gfx::Point(event->x, event->y), &transformed_point);
@@ -231,10 +255,7 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
event->x = transformed_point.x();
event->y = transformed_point.y();
- // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
- // https://crbug.com/613628
- ui::LatencyInfo latency_info;
- target->ProcessMouseWheelEvent(*event, latency_info);
+ target->ProcessMouseWheelEvent(*event, latency);
}
void RenderWidgetHostInputEventRouter::RouteGestureEvent(
@@ -432,8 +453,13 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
for (auto view : exited_views) {
blink::WebMouseEvent mouse_leave(*event);
mouse_leave.type = blink::WebInputEvent::MouseLeave;
- transformed_point = root_view->TransformPointToCoordSpaceForView(
- gfx::Point(event->x, event->y), view);
+ // There is a chance of a race if the last target has recently created a
+ // new compositor surface. The SurfaceID for that might not have
+ // propagated to its embedding surface, which makes it impossible to
+ // compute the transformation for it
+ if (!root_view->TransformPointToCoordSpaceForView(
+ gfx::Point(event->x, event->y), view, &transformed_point))
+ transformed_point = gfx::Point();
mouse_leave.x = transformed_point.x();
mouse_leave.y = transformed_point.y();
view->ProcessMouseEvent(mouse_leave, ui::LatencyInfo());
@@ -443,8 +469,10 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
if (common_ancestor && common_ancestor != target) {
blink::WebMouseEvent mouse_move(*event);
mouse_move.type = blink::WebInputEvent::MouseMove;
- transformed_point = root_view->TransformPointToCoordSpaceForView(
- gfx::Point(event->x, event->y), common_ancestor);
+ if (!root_view->TransformPointToCoordSpaceForView(
+ gfx::Point(event->x, event->y), common_ancestor,
+ &transformed_point))
+ transformed_point = gfx::Point();
mouse_move.x = transformed_point.x();
mouse_move.y = transformed_point.y();
common_ancestor->ProcessMouseEvent(mouse_move, ui::LatencyInfo());
@@ -456,8 +484,9 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
continue;
blink::WebMouseEvent mouse_enter(*event);
mouse_enter.type = blink::WebInputEvent::MouseMove;
- transformed_point = root_view->TransformPointToCoordSpaceForView(
- gfx::Point(event->x, event->y), view);
+ if (!root_view->TransformPointToCoordSpaceForView(
+ gfx::Point(event->x, event->y), view, &transformed_point))
+ transformed_point = gfx::Point();
mouse_enter.x = transformed_point.x();
mouse_enter.y = transformed_point.y();
view->ProcessMouseEvent(mouse_enter, ui::LatencyInfo());
@@ -483,11 +512,14 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
DCHECK(!first_bubbling_scroll_target_.target ==
!bubbling_gesture_scroll_target_.target);
+ ui::LatencyInfo latency_info =
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
+
// If target_view is already set up for bubbled scrolls, we forward
// the event to the current scroll target without further consideration.
if (target_view == first_bubbling_scroll_target_.target) {
- bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
- event, ui::LatencyInfo());
+ bubbling_gesture_scroll_target_.target->ProcessGestureEvent(event,
+ latency_info);
if (event.type == blink::WebInputEvent::GestureScrollEnd) {
first_bubbling_scroll_target_.target = nullptr;
bubbling_gesture_scroll_target_.target = nullptr;
@@ -505,8 +537,8 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
// have been sent to a renderer before the first one was ACKed, and the ACK
// caused a bubble retarget. In this case they all get forwarded.
if (target_view == bubbling_gesture_scroll_target_.target) {
- bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
- event, ui::LatencyInfo());
+ bubbling_gesture_scroll_target_.target->ProcessGestureEvent(event,
+ latency_info);
return;
}
@@ -531,7 +563,7 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
bubbling_gesture_scroll_target_.target = target_view;
SendGestureScrollBegin(target_view, event);
- target_view->ProcessGestureEvent(event, ui::LatencyInfo());
+ target_view->ProcessGestureEvent(event, latency_info);
}
void RenderWidgetHostInputEventRouter::SendGestureScrollBegin(
@@ -545,7 +577,9 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollBegin(
scroll_begin.data.scrollBegin.deltaYHint = event.data.scrollUpdate.deltaY;
scroll_begin.data.scrollBegin.deltaHintUnits =
event.data.scrollUpdate.deltaUnits;
- view->ProcessGestureEvent(scroll_begin, ui::LatencyInfo());
+ view->ProcessGestureEvent(
+ scroll_begin,
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event));
}
void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
@@ -560,7 +594,9 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
scroll_end.data.scrollEnd.inertialPhase =
event.data.scrollUpdate.inertialPhase;
scroll_end.data.scrollEnd.deltaUnits = event.data.scrollUpdate.deltaUnits;
- view->ProcessGestureEvent(scroll_end, ui::LatencyInfo());
+ view->ProcessGestureEvent(
+ scroll_end,
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event));
}
void RenderWidgetHostInputEventRouter::CancelScrollBubbling(
@@ -613,6 +649,8 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetHostAtPoint(
RenderWidgetHostViewBase* root_view,
const gfx::Point& point,
gfx::Point* transformed_point) {
+ if (!root_view)
+ return nullptr;
return RenderWidgetHostImpl::From(
FindEventTarget(root_view, point, transformed_point)
->GetRenderWidgetHost());
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 5c8f8eab821..721ccffa0fa 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
@@ -57,9 +57,11 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
RenderWidgetHostViewBase* view) override;
void RouteMouseEvent(RenderWidgetHostViewBase* root_view,
- blink::WebMouseEvent* event);
+ blink::WebMouseEvent* event,
+ const ui::LatencyInfo& latency);
void RouteMouseWheelEvent(RenderWidgetHostViewBase* root_view,
- blink::WebMouseWheelEvent* event);
+ blink::WebMouseWheelEvent* event,
+ const ui::LatencyInfo& latency);
void RouteGestureEvent(RenderWidgetHostViewBase* root_view,
blink::WebGestureEvent* event,
const ui::LatencyInfo& latency);
@@ -84,7 +86,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// Returns the RenderWidgetHostImpl inside the |root_view| at |point| where
// |point| is with respect to |root_view|'s coordinates. If a RWHI is found,
// the value of |transformed_point| is the coordinate of the point with
- // respect to the RWHI's coordinates.
+ // respect to the RWHI's coordinates. If |root_view| is nullptr, this method
+ // will return nullptr and will not modify |transformed_point|.
RenderWidgetHostImpl* GetRenderWidgetHostAtPoint(
RenderWidgetHostViewBase* root_view,
const gfx::Point& point,
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 a04ce104a16..69a7bcf618e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -17,7 +17,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -29,6 +28,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/screen.h"
@@ -40,6 +40,7 @@
#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/test/mock_gpu_channel_establish_factory.h"
+#include "ui/android/screen_android.h"
#endif
#if defined(USE_AURA) || defined(OS_MACOSX)
@@ -476,6 +477,7 @@ class RenderWidgetHostTest : public testing::Test {
ContextProviderFactoryImpl::Initialize(&gpu_channel_factory_);
ui::ContextProviderFactory::SetInstance(
ContextProviderFactoryImpl::GetInstance());
+ ui::SetScreenAndroid(); // calls display::Screen::SetScreenInstance().
#endif
#if defined(USE_AURA)
screen_.reset(aura::TestScreen::Create(gfx::Size()));
@@ -506,6 +508,7 @@ class RenderWidgetHostTest : public testing::Test {
ImageTransportFactory::Terminate();
#endif
#if defined(OS_ANDROID)
+ display::Screen::SetScreenInstance(nullptr);
ui::ContextProviderFactory::SetInstance(nullptr);
ContextProviderFactoryImpl::Terminate();
#endif
@@ -528,7 +531,7 @@ class RenderWidgetHostTest : public testing::Test {
void SendInputEventACK(WebInputEvent::Type type,
InputEventAckState ack_result) {
DCHECK(!WebInputEvent::isTouchEventType(type));
- InputEventAck ack(type, ack_result);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result);
host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
}
@@ -641,8 +644,6 @@ class RenderWidgetHostTest : public testing::Test {
return reinterpret_cast<const WebInputEvent*>(data);
}
- base::MessageLoopForUI message_loop_;
-
std::unique_ptr<TestBrowserContext> browser_context_;
RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
std::unique_ptr<MockRenderWidgetHostDelegate> delegate_;
@@ -661,6 +662,8 @@ class RenderWidgetHostTest : public testing::Test {
private:
SyntheticWebTouchEvent touch_event_;
+ TestBrowserThreadBundle thread_bundle_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
};
@@ -896,7 +899,6 @@ TEST_F(RenderWidgetHostTest, Background) {
// Test that we don't paint when we're hidden, but we still send the ACK. Most
// of the rest of the painting is tested in the GetBackingStore* ones.
TEST_F(RenderWidgetHostTest, HiddenPaint) {
- BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
// Hide the widget, it should have sent out a message to the renderer.
EXPECT_FALSE(host_->is_hidden_);
host_->WasHidden();
@@ -966,18 +968,23 @@ TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
// Forward the KeyUp event.
SimulateKeyboardEvent(WebInputEvent::KeyUp);
- // Make sure only KeyUp was sent to the renderer.
+ // Make sure the KeyUp event is suppressed.
+ EXPECT_EQ(0U, process_->sink().message_count());
+
+ // Simulate a new RawKeyDown event.
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(InputMsg_HandleInputEvent::ID,
process_->sink().GetMessageAt(0)->type());
process_->sink().ClearMessages();
// Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::KeyUp,
+ SendInputEventACK(WebInputEvent::RawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(delegate_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::KeyUp, delegate_->unhandled_keyboard_event_type());
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ delegate_->unhandled_keyboard_event_type());
}
TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
@@ -1092,14 +1099,14 @@ TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
// Start with a short timeout.
host_->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(10), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Immediately try to add a long 30 second timeout.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
host_->StartHangMonitorTimeout(
- TimeDelta::FromSeconds(30),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromSeconds(30), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1114,15 +1121,15 @@ TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
// Start with a short timeout, then stop it.
host_->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(10), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
host_->StopHangMonitorTimeout();
// Start it again to ensure it still works.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
host_->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(10), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1137,14 +1144,14 @@ TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) {
// Start with a timeout.
host_->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(100),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(100), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Start it again with shorter delay.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
host_->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(20),
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
+ TimeDelta::FromMilliseconds(20), WebInputEvent::Undefined,
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for the second timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1628,7 +1635,8 @@ TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
// Tests RWHI::ForwardTouchEventWithLatencyInfo().
PressTouchPoint(0, 1);
uint32_t touch_event_id = SendTouchEvent();
- InputEventAck ack(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
+ WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_event_id);
host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
CheckLatencyInfoComponentInMessage(
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 d8ce504b93c..e6a59122f15 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
@@ -82,8 +82,10 @@
#include "ui/base/layout.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/did_overscroll_params.h"
+#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/android/device_display_info.h"
@@ -449,6 +451,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
this),
stylus_text_selector_(this),
using_browser_compositor_(CompositorImpl::IsInitialized()),
+ synchronous_compositor_client_(nullptr),
frame_evictor_(new DelegatedFrameEvictor(this)),
locks_on_frame_count_(0),
observing_root_window_(false),
@@ -599,12 +602,6 @@ void RenderWidgetHostViewAndroid::Focus() {
host_->Focus();
if (overscroll_controller_)
overscroll_controller_->Enable();
- if (content_view_core_) {
- WebContentsImpl* web_contents_impl =
- static_cast<WebContentsImpl*>(content_view_core_->GetWebContents());
- if (web_contents_impl->ShowingInterstitialPage())
- content_view_core_->ForceUpdateImeAdapter(GetNativeImeAdapter());
- }
}
bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -724,18 +721,18 @@ gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
return content_view_core_->GetPhysicalBackingSize();
}
-bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
+bool RenderWidgetHostViewAndroid::DoBrowserControlsShrinkBlinkSize() const {
// Whether or not Blink's viewport size should be shrunk by the height of the
// URL-bar.
return content_view_core_ &&
- content_view_core_->DoTopControlsShrinkBlinkSize();
+ content_view_core_->DoBrowserControlsShrinkBlinkSize();
}
float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
if (!content_view_core_)
return default_bounds_.x();
- // The height of the top controls.
+ // The height of the browser controls.
return content_view_core_->GetTopControlsHeightDip();
}
@@ -743,7 +740,7 @@ float RenderWidgetHostViewAndroid::GetBottomControlsHeight() const {
if (!content_view_core_)
return 0.f;
- // The height of the top controls.
+ // The height of the browser controls.
return content_view_core_->GetBottomControlsHeightDip();
}
@@ -842,7 +839,7 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
event, result.moved_beyond_slop_region);
- ui::LatencyInfo latency_info;
+ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
host_->ForwardTouchEventWithLatencyInfo(web_event, latency_info);
@@ -875,9 +872,11 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
std::unique_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
bool causes_scrolling = false;
+ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
host_->ForwardTouchEventWithLatencyInfo(
ui::CreateWebTouchEventFromMotionEvent(*cancel_event, causes_scrolling),
- ui::LatencyInfo());
+ latency_info);
}
}
@@ -978,7 +977,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
return;
}
- if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
+ if (!(view_.GetWindowAndroid())) {
callback.Run(SkBitmap(), READBACK_FAILED);
return;
}
@@ -1001,7 +1000,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
}
ui::WindowAndroidCompositor* compositor =
- content_view_core_->GetWindowAndroid()->GetCompositor();
+ view_.GetWindowAndroid()->GetCompositor();
DCHECK(compositor);
DCHECK(delegated_frame_host_);
scoped_refptr<PendingReadbackLock> readback_lock(
@@ -1190,17 +1189,19 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
OnFrameMetadataUpdated(frame_metadata.Clone(), false);
// DevTools ScreenCast support for Android WebView.
- WebContents* web_contents = content_view_core_->GetWebContents();
- if (DevToolsAgentHost::HasFor(web_contents)) {
- scoped_refptr<DevToolsAgentHost> dtah =
- DevToolsAgentHost::GetOrCreateFor(web_contents);
- // Unblock the compositor.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
- static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
- base::Passed(&frame_metadata)));
+ RenderFrameHost* frame_host = RenderViewHost::From(host_)->GetMainFrame();
+ if (frame_host) {
+ RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
+ frame_host,
+ std::move(frame_metadata));
+ }
+}
+
+void RenderWidgetHostViewAndroid::SetSynchronousCompositorClient(
+ SynchronousCompositorClient* client) {
+ synchronous_compositor_client_ = client;
+ if (!sync_compositor_ && synchronous_compositor_client_) {
+ sync_compositor_ = SynchronousCompositorHost::Create(this);
}
}
@@ -1211,9 +1212,9 @@ bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
}
void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
- DCHECK(content_view_core_ && content_view_core_->GetWindowAndroid());
+ DCHECK(view_.GetWindowAndroid());
DCHECK(using_browser_compositor_);
- content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
+ view_.GetWindowAndroid()->SetNeedsAnimate();
}
void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
@@ -1425,7 +1426,7 @@ void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32_t requests) {
// vsync requests will be pushed if/when we resume observing in
// |StartObservingRootWindow()|.
if (observing_root_window_ && should_request_vsync) {
- ui::WindowAndroid* windowAndroid = content_view_core_->GetWindowAndroid();
+ ui::WindowAndroid* windowAndroid = view_.GetWindowAndroid();
DCHECK(windowAndroid);
// TODO(boliu): This check should be redundant with
// |observing_root_window_| check above. However we are receiving trickle
@@ -1440,7 +1441,7 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
DCHECK(content_view_core_);
// TODO(yusufo): This will need to have a better fallback for cases where
// setContentViewCore is called with a valid ContentViewCore without a window.
- DCHECK(content_view_core_->GetWindowAndroid());
+ DCHECK(view_.GetWindowAndroid());
DCHECK(is_showing_);
if (observing_root_window_)
return;
@@ -1448,7 +1449,7 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
observing_root_window_ = true;
if (host_)
host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), false));
- content_view_core_->GetWindowAndroid()->AddObserver(this);
+ view_.GetWindowAndroid()->AddObserver(this);
// Clear existing vsync requests to allow a request to the new window.
uint32_t outstanding_vsync_requests = outstanding_vsync_requests_;
@@ -1456,7 +1457,7 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
RequestVSyncUpdate(outstanding_vsync_requests);
ui::WindowAndroidCompositor* compositor =
- content_view_core_->GetWindowAndroid()->GetCompositor();
+ view_.GetWindowAndroid()->GetCompositor();
if (compositor) {
delegated_frame_host_->RegisterFrameSinkHierarchy(
compositor->GetFrameSinkId());
@@ -1464,7 +1465,7 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
}
void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
- if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
+ if (!(view_.GetWindowAndroid())) {
DCHECK(!observing_root_window_);
return;
}
@@ -1478,7 +1479,7 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
observing_root_window_ = false;
if (host_)
host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), true));
- content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+ view_.GetWindowAndroid()->RemoveObserver(this);
// If the DFH has already been destroyed, it will have cleaned itself up.
// This happens in some WebView cases.
if (delegated_frame_host_)
@@ -1500,7 +1501,7 @@ void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
vsync_period, cc::BeginFrameArgs::NORMAL)));
if (sync_compositor_)
- sync_compositor_->DidSendBeginFrame(content_view_core_->GetWindowAndroid());
+ sync_compositor_->DidSendBeginFrame(view_.GetWindowAndroid());
}
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
@@ -1656,15 +1657,33 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
}
void RenderWidgetHostViewAndroid::SendMouseEvent(
- const blink::WebMouseEvent& event) {
+ const ui::MotionEventAndroid& motion_event,
+ int changed_button) {
+ blink::WebInputEvent::Type webMouseEventType =
+ ui::ToWebMouseEventType(motion_event.GetAction());
+
+ blink::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(
+ webMouseEventType,
+ ui::EventTimeStampToSeconds(motion_event.GetEventTime()),
+ motion_event.GetX(0),
+ motion_event.GetY(0),
+ motion_event.GetFlags(),
+ motion_event.GetButtonState() ? 1 : 0 /* click count */,
+ motion_event.GetPointerId(0),
+ motion_event.GetPressure(0),
+ motion_event.GetOrientation(0),
+ motion_event.GetTilt(0),
+ changed_button,
+ motion_event.GetToolType(0));
+
if (host_)
- host_->ForwardMouseEvent(event);
+ host_->ForwardMouseEvent(mouse_event);
}
void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
const blink::WebMouseWheelEvent& event) {
if (host_) {
- ui::LatencyInfo latency_info;
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
host_->ForwardWheelEventWithLatencyInfo(event, latency_info);
}
@@ -1676,8 +1695,11 @@ void RenderWidgetHostViewAndroid::SendGestureEvent(
if (overscroll_controller_)
overscroll_controller_->Enable();
- if (host_)
- host_->ForwardGestureEventWithLatencyInfo(event, ui::LatencyInfo());
+ if (host_) {
+ ui::LatencyInfo latency_info =
+ ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
+ host_->ForwardGestureEventWithLatencyInfo(event, latency_info);
+ }
}
void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
@@ -1695,27 +1717,6 @@ void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
selection_controller_->SetTemporarilyHidden(hidden);
}
-void RenderWidgetHostViewAndroid::OnShowingPastePopup(
- const gfx::PointF& point) {
- if (!selection_controller_)
- return;
-
- // As the paste popup may be triggered *before* the bounds and editability
- // of the region have been updated, explicitly set the properties now.
- // TODO(jdduke): Remove this workaround when auxiliary paste popup
- // notifications are no longer required, crbug.com/398170.
- gfx::SelectionBound insertion_bound;
- insertion_bound.set_type(gfx::SelectionBound::CENTER);
- insertion_bound.set_visible(true);
- insertion_bound.SetEdge(point, point);
- selection_controller_->HideAndDisallowShowingAutomatically();
- selection_controller_->OnSelectionEditable(true);
- selection_controller_->OnSelectionEmpty(true);
- selection_controller_->OnSelectionBoundsChanged(insertion_bound,
- insertion_bound);
- selection_controller_->AllowShowingFromCurrentSelection();
-}
-
SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
return cached_background_color_;
}
@@ -1801,15 +1802,10 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
selection_controller_ = CreateSelectionController(this, content_view_core_);
if (!overscroll_controller_ &&
- content_view_core_->GetWindowAndroid()->GetCompositor()) {
+ view_.GetWindowAndroid()->GetCompositor()) {
overscroll_controller_ = CreateOverscrollController(
content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView()));
}
-
- if (!sync_compositor_) {
- sync_compositor_ = SynchronousCompositorHost::Create(
- this, content_view_core_->GetWebContents());
- }
}
void RenderWidgetHostViewAndroid::RunAckCallbacks() {
@@ -1861,8 +1857,8 @@ void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
void RenderWidgetHostViewAndroid::OnAttachedToWindow() {
if (is_showing_)
StartObservingRootWindow();
- DCHECK(content_view_core_ && content_view_core_->GetWindowAndroid());
- if (content_view_core_->GetWindowAndroid()->GetCompositor())
+ DCHECK(view_.GetWindowAndroid());
+ if (view_.GetWindowAndroid()->GetCompositor())
OnAttachCompositor();
}
@@ -1877,7 +1873,7 @@ void RenderWidgetHostViewAndroid::OnAttachCompositor() {
overscroll_controller_ = CreateOverscrollController(
content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView()));
ui::WindowAndroidCompositor* compositor =
- content_view_core_->GetWindowAndroid()->GetCompositor();
+ view_.GetWindowAndroid()->GetCompositor();
delegated_frame_host_->RegisterFrameSinkHierarchy(
compositor->GetFrameSinkId());
}
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 573d4313b8e..0ac77152c1d 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
@@ -32,17 +32,17 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android_observer.h"
+#include "ui/events/android/motion_event_android.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/selection_bound.h"
#include "ui/touch_selection/touch_selection_controller.h"
+class GURL;
+
namespace cc {
-class CopyOutputResult;
class Layer;
-class SurfaceFactory;
-class SurfaceIdAllocator;
}
namespace ui {
@@ -50,8 +50,6 @@ struct DidOverscrollParams;
}
namespace blink {
-class WebExternalTextureLayer;
-class WebTouchEvent;
class WebMouseEvent;
}
@@ -61,11 +59,11 @@ class DelegatedFrameHostAndroid;
namespace content {
class ContentViewCoreImpl;
-class ContentViewCoreObserver;
class OverscrollControllerAndroid;
class RenderWidgetHost;
class RenderWidgetHostImpl;
class SynchronousCompositorHost;
+class SynchronousCompositorClient;
struct NativeWebKeyboardEvent;
struct TextInputState;
@@ -108,7 +106,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
gfx::Rect GetViewBounds() const override;
gfx::Size GetVisibleViewportSize() const override;
gfx::Size GetPhysicalBackingSize() const override;
- bool DoTopControlsShrinkBlinkSize() const override;
+ bool DoBrowserControlsShrinkBlinkSize() const override;
float GetTopControlsHeight() const override;
float GetBottomControlsHeight() const override;
void UpdateCursor(const WebCursor& cursor) override;
@@ -208,7 +206,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
SkColor GetCachedBackgroundColor() const;
void SendKeyEvent(const NativeWebKeyboardEvent& event);
- void SendMouseEvent(const blink::WebMouseEvent& event);
+ void SendMouseEvent(const ui::MotionEventAndroid&, int changed_button);
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
void SendGestureEvent(const blink::WebGestureEvent& event);
@@ -237,11 +235,16 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void MoveCaret(const gfx::Point& point);
void DismissTextHandles();
void SetTextHandlesTemporarilyHidden(bool hidden);
- void OnShowingPastePopup(const gfx::PointF& point);
void OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip);
void SynchronousFrameMetadata(cc::CompositorFrameMetadata frame_metadata);
+ void SetSynchronousCompositorClient(SynchronousCompositorClient* client);
+
+ SynchronousCompositorClient* synchronous_compositor_client() const {
+ return synchronous_compositor_client_;
+ }
+
static void OnContextLost();
private:
@@ -356,6 +359,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const bool using_browser_compositor_;
std::unique_ptr<SynchronousCompositorHost> sync_compositor_;
+ SynchronousCompositorClient* synchronous_compositor_client_;
+
std::unique_ptr<DelegatedFrameEvictor> frame_evictor_;
size_t locks_on_frame_count_;
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 3992bb0f837..59178ae073a 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
@@ -41,6 +41,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_input_event_router.h"
+#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/content_switches_internal.h"
#include "content/common/input_messages.h"
@@ -55,14 +56,15 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
#include "gpu/ipc/common/gpu_messages.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/cursor_client_observer.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/client/transient_window_client.h"
+#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
@@ -91,7 +93,6 @@
#include "ui/wm/public/activation_client.h"
#include "ui/wm/public/scoped_tooltip_disabler.h"
#include "ui/wm/public/tooltip_client.h"
-#include "ui/wm/public/transient_window_client.h"
#include "ui/wm/public/window_types.h"
#if defined(OS_WIN)
@@ -122,15 +123,6 @@ namespace content {
namespace {
-// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
-// the border of the view, in order to get valid movement information. However,
-// forcing the cursor back to the center of the view after each mouse move
-// doesn't work well. It reduces the frequency of useful mouse move messages
-// significantly. Therefore, we move the cursor to the center of the view only
-// if it approaches the border. |kMouseLockBorderPercentage| specifies the width
-// of the border area, in percentage of the corresponding dimension.
-const int kMouseLockBorderPercentage = 15;
-
// When accelerated compositing is enabled and a widget resize is pending,
// we delay further resizes of the UI. The following constant is the maximum
// length of time that we should delay further UI resizes while waiting for a
@@ -138,67 +130,7 @@ const int kMouseLockBorderPercentage = 15;
const int kResizeLockTimeoutMs = 67;
#if defined(OS_WIN)
-// A callback function for EnumThreadWindows to enumerate and dismiss
-// any owned popup windows.
-BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
- const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
-
- if (::IsWindowVisible(window)) {
- const HWND owner = ::GetWindow(window, GW_OWNER);
- if (toplevel_hwnd == owner) {
- ::PostMessage(window, WM_CANCELMODE, 0, 0);
- }
- }
- return TRUE;
-}
-#endif
-
-// We don't mark these as handled so that they're sent back to the
-// DefWindowProc so it can generate WM_APPCOMMAND as necessary.
-bool IsXButtonUpEvent(const ui::MouseEvent* event) {
-#if defined(OS_WIN)
- switch (event->native_event().message) {
- case WM_XBUTTONUP:
- case WM_NCXBUTTONUP:
- return true;
- }
-#endif
- return false;
-}
-
-bool IsFractionalScaleFactor(float scale_factor) {
- return (scale_factor - static_cast<int>(scale_factor)) > 0;
-}
-
-// Reset unchanged touch point to StateStationary for touchmove and
-// touchcancel.
-void MarkUnchangedTouchPointsAsStationary(
- blink::WebTouchEvent* event,
- int changed_touch_id) {
- if (event->type == blink::WebInputEvent::TouchMove ||
- event->type == blink::WebInputEvent::TouchCancel) {
- for (size_t i = 0; i < event->touchesLength; ++i) {
- if (event->touches[i].id != changed_touch_id)
- event->touches[i].state = blink::WebTouchPoint::StateStationary;
- }
- }
-}
-
-gfx::Point GetScreenLocationFromEvent(const ui::LocatedEvent& event) {
- aura::Window* root =
- static_cast<aura::Window*>(event.target())->GetRootWindow();
- aura::client::ScreenPositionClient* spc =
- aura::client::GetScreenPositionClient(root);
- if (!spc)
- return event.root_location();
-
- gfx::Point screen_location(event.root_location());
- spc->ConvertPointToScreen(root, &screen_location);
- return screen_location;
-}
-
-#if defined(OS_WIN)
// This class implements the ui::OnScreenKeyboardObserver interface
// which provides notifications about the on screen keyboard on Windows getting
// displayed or hidden in response to taps on editable fields.
@@ -253,6 +185,8 @@ class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
gfx::Point origin(location_in_screen_);
screen_position_client->ConvertPointFromScreen(window_, &origin);
+ // TODO(ekaramad): We should support the case where the focused node is
+ // inside an OOPIF (https://crbug.com/676037).
// We want to scroll the node into a rectangle which originates from
// the touch point and a small offset (10) in either direction.
gfx::Rect node_rect(origin.x(), origin.y(), 10, 10);
@@ -277,7 +211,7 @@ class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
DISALLOW_COPY_AND_ASSIGN(WinScreenKeyboardObserver);
};
-#endif
+#endif // defined(OS_WIN)
} // namespace
@@ -331,7 +265,8 @@ void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
// notification. We also set a flag in the view indicating that we need
// to force a Focus notification on the next mouse down.
if (popup_parent_host_view_ && popup_parent_host_view_->host_) {
- popup_parent_host_view_->set_focus_on_mouse_down_or_key_event_ = true;
+ popup_parent_host_view_->event_handler()
+ ->set_focus_on_mouse_down_or_key_event(true);
popup_parent_host_view_->host_->Blur();
}
// Note: popup_parent_host_view_ may be NULL when there are multiple
@@ -432,16 +367,14 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
window_(nullptr),
in_shutdown_(false),
in_bounds_changed_(false),
- is_fullscreen_(false),
popup_parent_host_view_(nullptr),
popup_child_host_view_(nullptr),
is_loading_(false),
has_composition_text_(false),
- accept_return_character_(false),
begin_frame_source_(nullptr),
needs_begin_frames_(false),
+ needs_flush_input_(false),
added_frame_observer_(false),
- synthetic_move_sent_(false),
cursor_visibility_state_in_renderer_(UNKNOWN),
#if defined(OS_WIN)
legacy_render_widget_host_HWND_(nullptr),
@@ -450,11 +383,10 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
#endif
has_snapped_to_boundary_(false),
is_guest_view_hack_(is_guest_view_hack),
- set_focus_on_mouse_down_or_key_event_(false),
device_scale_factor_(0.0f),
- disable_input_event_router_for_testing_(false),
last_active_widget_process_id_(ChildProcessHost::kInvalidUniqueID),
last_active_widget_routing_id_(MSG_ROUTING_NONE),
+ event_handler_(new RenderWidgetHostViewEventHandler(host_, this, this)),
weak_ptr_factory_(this) {
// GuestViews have two RenderWidgetHostViews and so we need to make sure
// we don't have FrameSinkId collisions.
@@ -541,7 +473,7 @@ void RenderWidgetHostViewAura::InitAsPopup(
}
old_child->popup_parent_host_view_ = NULL;
}
- popup_parent_host_view_->popup_child_host_view_ = this;
+ popup_parent_host_view_->SetPopupChild(this);
window_->SetType(ui::wm::WINDOW_TYPE_MENU);
window_->Init(ui::LAYER_SOLID_COLOR);
window_->SetName("RenderWidgetHostViewAura");
@@ -586,10 +518,7 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
if (reference_host_view) {
aura::Window* reference_window =
static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
- if (reference_window) {
- host_tracker_.reset(new aura::WindowTracker);
- host_tracker_->Add(reference_window);
- }
+ event_handler_->TrackHost(reference_window);
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(reference_window);
parent = reference_window->GetRootWindow();
@@ -729,22 +658,31 @@ void RenderWidgetHostViewAura::SetNeedsBeginFrames(bool needs_begin_frames) {
UpdateNeedsBeginFramesInternal();
}
+void RenderWidgetHostViewAura::OnSetNeedsFlushInput() {
+ needs_flush_input_ = true;
+ UpdateNeedsBeginFramesInternal();
+}
+
void RenderWidgetHostViewAura::UpdateNeedsBeginFramesInternal() {
if (!begin_frame_source_)
return;
- if (added_frame_observer_ == needs_begin_frames_)
+ bool needs_frame = needs_begin_frames_ || needs_flush_input_;
+ if (needs_frame == added_frame_observer_)
return;
- if (needs_begin_frames_)
+ added_frame_observer_ = needs_frame;
+ if (needs_frame)
begin_frame_source_->AddObserver(this);
else
begin_frame_source_->RemoveObserver(this);
- added_frame_observer_ = needs_begin_frames_;
}
void RenderWidgetHostViewAura::OnBeginFrame(
const cc::BeginFrameArgs& args) {
+ needs_flush_input_ = false;
+ host_->FlushInput();
+ UpdateNeedsBeginFramesInternal();
host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
last_begin_frame_args_ = args;
}
@@ -758,24 +696,6 @@ void RenderWidgetHostViewAura::OnBeginFrameSourcePausedChanged(bool paused) {
// Only used on Android WebView.
}
-void RenderWidgetHostViewAura::SetKeyboardFocus() {
-#if defined(OS_WIN)
- if (CanFocus()) {
- aura::WindowTreeHost* host = window_->GetHost();
- if (host) {
- gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget();
- if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE))
- ::SetFocus(hwnd);
- }
- }
-#endif
- // TODO(wjmaclean): can host_ ever be null?
- if (host_ && set_focus_on_mouse_down_or_key_event_) {
- set_focus_on_mouse_down_or_key_event_ = false;
- host_->Focus();
- }
-}
-
RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
RenderViewHost* rvh = RenderViewHost::From(host_);
if (!rvh)
@@ -788,88 +708,6 @@ RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
return focused_frame->current_frame_host();
}
-bool RenderWidgetHostViewAura::CanRendererHandleEvent(
- const ui::MouseEvent* event,
- bool mouse_locked,
- bool selection_popup) const {
- if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
- return false;
-
- if (event->type() == ui::ET_MOUSE_EXITED) {
- if (mouse_locked || selection_popup)
- return false;
-#if defined(OS_WIN)
- // Don't forward the mouse leave message which is received when the context
- // menu is displayed by the page. This confuses the page and causes state
- // changes.
- if (IsShowingContextMenu())
- return false;
-#endif
- return true;
- }
-
-#if defined(OS_WIN)
- // Renderer cannot handle WM_XBUTTON or NC events.
- switch (event->native_event().message) {
- case WM_XBUTTONDOWN:
- case WM_XBUTTONUP:
- case WM_XBUTTONDBLCLK:
- case WM_NCMOUSELEAVE:
- case WM_NCMOUSEMOVE:
- case WM_NCLBUTTONDOWN:
- case WM_NCLBUTTONUP:
- case WM_NCLBUTTONDBLCLK:
- case WM_NCRBUTTONDOWN:
- case WM_NCRBUTTONUP:
- case WM_NCRBUTTONDBLCLK:
- case WM_NCMBUTTONDOWN:
- case WM_NCMBUTTONUP:
- case WM_NCMBUTTONDBLCLK:
- case WM_NCXBUTTONDOWN:
- case WM_NCXBUTTONUP:
- case WM_NCXBUTTONDBLCLK:
- return false;
- default:
- break;
- }
-#elif defined(USE_X11)
- // Renderer only supports standard mouse buttons, so ignore programmable
- // buttons.
- switch (event->type()) {
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED: {
- const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
- ui::EF_MIDDLE_MOUSE_BUTTON |
- ui::EF_RIGHT_MOUSE_BUTTON;
- return (event->flags() & kAllowedButtons) != 0;
- }
- default:
- break;
- }
-#endif
- return true;
-}
-
-bool RenderWidgetHostViewAura::ShouldRouteEvent(const ui::Event* event) const {
- // We should route an event in two cases:
- // 1) Mouse events are routed only if cross-process frames are possible.
- // 2) Touch events are always routed. In the absence of a BrowserPlugin
- // we expect the routing to always send the event to this view. If
- // one or more BrowserPlugins are present, then the event may be targeted
- // to one of them, or this view. This allows GuestViews to have access to
- // them while still forcing pinch-zoom to be handled by the top-level
- // frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but
- // it should be a simple extension to modify RenderWidgetHostViewChildFrame
- // in a similar manner to RenderWidgetHostViewGuest.
- bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() &&
- !disable_input_event_router_for_testing_;
- // 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;
-}
-
void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
SnapToPhysicalPixelBoundary();
#if defined(OS_WIN)
@@ -920,6 +758,8 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
}
void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
+ if (color == background_color())
+ return;
RenderWidgetHostViewBase::SetBackgroundColor(color);
bool opaque = GetBackgroundOpaque();
host_->SetBackgroundOpaque(opaque);
@@ -927,6 +767,10 @@ void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
window_->layer()->SetColor(color);
}
+bool RenderWidgetHostViewAura::IsMouseLocked() {
+ return event_handler_->mouse_locked();
+}
+
gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
gfx::Rect requested_rect(GetRequestedRendererSize());
requested_rect.Inset(insets_);
@@ -951,7 +795,7 @@ void RenderWidgetHostViewAura::FocusedNodeTouched(
ui::OnScreenKeyboardDisplayManager* osk_display_manager =
ui::OnScreenKeyboardDisplayManager::GetInstance();
DCHECK(osk_display_manager);
- if (editable && host_ && host_->GetView()) {
+ if (editable && host_ && host_->GetView() && host_->delegate()) {
keyboard_observer_.reset(new WinScreenKeyboardObserver(
host_, location_dips_screen, device_scale_factor_, window_));
virtual_keyboard_requested_ =
@@ -1066,6 +910,12 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
cc::CompositorFrame frame) {
TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
+ // Override the background color to the current compositor background.
+ // This allows us to, when navigating to a new page, transfer this color to
+ // that page. This allows us to pass this background color to new views on
+ // navigation.
+ SetBackgroundColor(frame.metadata.root_background_color);
+
last_scroll_offset_ = frame.metadata.root_scroll_offset;
if (!frame.delegated_frame_data)
return;
@@ -1291,66 +1141,11 @@ RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
}
bool RenderWidgetHostViewAura::LockMouse() {
- aura::Window* root_window = window_->GetRootWindow();
- if (!root_window)
- return false;
-
- if (mouse_locked_)
- return true;
-
- mouse_locked_ = true;
-#if !defined(OS_WIN)
- window_->SetCapture();
-#else
- UpdateMouseLockRegion();
-#endif
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- cursor_client->HideCursor();
- cursor_client->LockCursor();
- }
-
- if (ShouldMoveToCenter()) {
- synthetic_move_sent_ = true;
- window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
- }
- tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
- return true;
+ return event_handler_->LockMouse();
}
void RenderWidgetHostViewAura::UnlockMouse() {
- tooltip_disabler_.reset();
-
- aura::Window* root_window = window_->GetRootWindow();
- if (!mouse_locked_ || !root_window)
- return;
-
- mouse_locked_ = false;
-
- if (window_->HasCapture())
- window_->ReleaseCapture();
-
-#if defined(OS_WIN)
- ::ClipCursor(NULL);
-#endif
-
- // Ensure that the global mouse position is updated here to its original
- // value. If we don't do this then the synthesized mouse move which is posted
- // after the cursor is moved ends up getting a large movement delta which is
- // not what sites expect. The delta is computed in the
- // ModifyEventMovementAndCoords function.
- global_mouse_position_ = unlocked_global_mouse_position_;
- window_->MoveCursorTo(unlocked_mouse_position_);
-
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- cursor_client->UnlockCursor();
- cursor_client->ShowCursor();
- }
-
- host_->LostMouseLock();
+ event_handler_->UnlockMouse();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1420,8 +1215,8 @@ void RenderWidgetHostViewAura::InsertChar(const ui::KeyEvent& event) {
// Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
// TODO(wjmaclean): can host_ ever be null?
- if (host_ &&
- (accept_return_character_ || event.GetCharacter() != ui::VKEY_RETURN)) {
+ if (host_ && (event_handler_->accept_return_character() ||
+ event.GetCharacter() != ui::VKEY_RETURN)) {
// Send a blink::WebInputEvent::Char event to |host_|.
ForwardKeyboardEvent(NativeWebKeyboardEvent(event, event.GetCharacter()));
}
@@ -1790,221 +1585,11 @@ void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
// RenderWidgetHostViewAura, ui::EventHandler implementation:
void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
-
- if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
- popup_child_host_view_->OnKeyEvent(event);
- if (event->handled())
- return;
- }
-
- // We need to handle the Escape key for Pepper Flash.
- if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
- // Focus the window we were created from.
- if (host_tracker_.get() && !host_tracker_->windows().empty()) {
- aura::Window* host = *(host_tracker_->windows().begin());
- aura::client::FocusClient* client = aura::client::GetFocusClient(host);
- if (client) {
- // Calling host->Focus() may delete |this|. We create a local observer
- // for that. In that case we exit without further access to any members.
- aura::WindowTracker tracker;
- aura::Window* window = window_;
- tracker.Add(window);
- host->Focus();
- if (!tracker.Contains(window)) {
- event->SetHandled();
- return;
- }
- }
- }
- Shutdown();
- } else {
- if (event->key_code() == ui::VKEY_RETURN) {
- // Do not forward return key release events if no press event was handled.
- if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
- return;
- // Accept return key character events between press and release events.
- accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
- }
-
- // Call SetKeyboardFocus() for not only ET_KEY_PRESSED but also
- // ET_KEY_RELEASED. If a user closed the hotdog menu with ESC key press,
- // we need to notify focus to Blink on ET_KEY_RELEASED for ESC key.
- SetKeyboardFocus();
- // We don't have to communicate with an input method here.
- NativeWebKeyboardEvent webkit_event(*event);
- ForwardKeyboardEvent(webkit_event);
- }
- event->SetHandled();
+ event_handler_->OnKeyEvent(event);
}
void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
-
- ForwardMouseEventToParent(event);
- // TODO(mgiuca): Return if event->handled() returns true. This currently
- // breaks drop-down lists which means something is incorrectly setting
- // event->handled to true (http://crbug.com/577983).
-
- if (mouse_locked_) {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
-
- if (event->type() == ui::ET_MOUSEWHEEL) {
- blink::WebMouseWheelEvent mouse_wheel_event =
- ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
- base::Bind(&GetScreenLocationFromEvent));
- if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
- host_->ForwardWheelEvent(mouse_wheel_event);
- return;
- }
-
- gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
-
- // If we receive non client mouse messages while we are in the locked state
- // it probably means that the mouse left the borders of our window and
- // needs to be moved back to the center.
- if (event->flags() & ui::EF_IS_NON_CLIENT) {
- synthetic_move_sent_ = true;
- window_->MoveCursorTo(center);
- return;
- }
-
- blink::WebMouseEvent mouse_event =
- ui::MakeWebMouseEvent(*event, base::Bind(&GetScreenLocationFromEvent));
-
- bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_DRAGGED) &&
- mouse_event.x == center.x() && mouse_event.y == center.y();
-
- // For fractional scale factors, the conversion from pixels to dip and
- // vice versa could result in off by 1 or 2 errors which hurts us because
- // we want to avoid sending the artificial move to center event to the
- // renderer. Sending the move to center to the renderer cause the cursor
- // to bounce around the center of the screen leading to the lock operation
- // not working correctly.
- // Workaround is to treat a mouse move or drag event off by at most 2 px
- // from the center as a move to center event.
- if (synthetic_move_sent_ &&
- IsFractionalScaleFactor(current_device_scale_factor_)) {
- if (event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_DRAGGED) {
- if ((abs(mouse_event.x - center.x()) <= 2) &&
- (abs(mouse_event.y - center.y()) <= 2)) {
- is_move_to_center_event = true;
- }
- }
- }
-
- ModifyEventMovementAndCoords(&mouse_event);
-
- bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
- if (should_not_forward) {
- synthetic_move_sent_ = false;
- } else {
- // Check if the mouse has reached the border and needs to be centered.
- if (ShouldMoveToCenter()) {
- synthetic_move_sent_ = true;
- window_->MoveCursorTo(center);
- }
- bool is_selection_popup = popup_child_host_view_ &&
- popup_child_host_view_->NeedsInputGrab();
- // Forward event to renderer.
- if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
- !(event->flags() & ui::EF_FROM_TOUCH)) {
- host_->ForwardMouseEvent(mouse_event);
- // Ensure that we get keyboard focus on mouse down as a plugin window
- // may have grabbed keyboard focus.
- if (event->type() == ui::ET_MOUSE_PRESSED)
- SetKeyboardFocus();
- }
- }
- return;
- }
-
- // As the overscroll is handled during scroll events from the trackpad, the
- // RWHVA window is transformed by the overscroll controller. This transform
- // triggers a synthetic mouse-move event to be generated (by the aura
- // RootWindow). But this event interferes with the overscroll gesture. So,
- // ignore such synthetic mouse-move events if an overscroll gesture is in
- // progress.
- if (overscroll_controller_ &&
- overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE &&
- event->flags() & ui::EF_IS_SYNTHESIZED &&
- (event->type() == ui::ET_MOUSE_ENTERED ||
- event->type() == ui::ET_MOUSE_EXITED ||
- event->type() == ui::ET_MOUSE_MOVED)) {
- event->StopPropagation();
- return;
- }
-
- if (event->type() == ui::ET_MOUSEWHEEL) {
-#if defined(OS_WIN)
- // We get mouse wheel/scroll messages even if we are not in the foreground.
- // So here we check if we have any owned popup windows in the foreground and
- // dismiss them.
- aura::WindowTreeHost* host = window_->GetHost();
- if (host) {
- HWND parent = host->GetAcceleratedWidget();
- HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
- EnumThreadWindows(GetCurrentThreadId(),
- DismissOwnedPopups,
- reinterpret_cast<LPARAM>(toplevel_hwnd));
- }
-#endif
- blink::WebMouseWheelEvent mouse_wheel_event =
- ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
- base::Bind(&GetScreenLocationFromEvent));
- if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) {
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
- this, &mouse_wheel_event);
- } else {
- ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
- }
- }
- } else {
- bool is_selection_popup =
- popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab();
- if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
- !(event->flags() & ui::EF_FROM_TOUCH)) {
- // Confirm existing composition text on mouse press, to make sure
- // the input caret won't be moved with an ongoing composition text.
- if (event->type() == ui::ET_MOUSE_PRESSED)
- FinishImeCompositionSession();
-
- blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
- ModifyEventMovementAndCoords(&mouse_event);
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteMouseEvent(this,
- &mouse_event);
- } else {
- ProcessMouseEvent(mouse_event, *event->latency());
- }
-
- // Ensure that we get keyboard focus on mouse down as a plugin window may
- // have grabbed keyboard focus.
- if (event->type() == ui::ET_MOUSE_PRESSED)
- SetKeyboardFocus();
- }
- }
-
- switch (event->type()) {
- case ui::ET_MOUSE_PRESSED:
- window_->SetCapture();
- break;
- case ui::ET_MOUSE_RELEASED:
- if (!NeedsMouseCapture())
- window_->ReleaseCapture();
- break;
- default:
- break;
- }
-
- if (!IsXButtonUpEvent(event))
- event->SetHandled();
+ event_handler_->OnMouseEvent(event);
}
cc::FrameSinkId RenderWidgetHostViewAura::FrameSinkIdAtPoint(
@@ -2024,7 +1609,7 @@ cc::FrameSinkId RenderWidgetHostViewAura::FrameSinkIdAtPoint(
// It is possible that the renderer has not yet produced a surface, in which
// case we return our current namespace.
- if (id.is_null())
+ if (!id.is_valid())
return GetFrameSinkId();
return id.frame_sink_id();
}
@@ -2053,27 +1638,36 @@ void RenderWidgetHostViewAura::ProcessGestureEvent(
host_->ForwardGestureEventWithLatencyInfo(event, latency);
}
-gfx::Point RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) {
- gfx::Point transformed_point;
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) {
// Transformations use physical pixels rather than DIP, so conversion
// is necessary.
gfx::Point point_in_pixels =
gfx::ConvertPointToPixel(device_scale_factor_, point);
- transformed_point = delegated_frame_host_->TransformPointToLocalCoordSpace(
- point_in_pixels, original_surface);
- return gfx::ConvertPointToDIP(device_scale_factor_, transformed_point);
+ if (!delegated_frame_host_->TransformPointToLocalCoordSpace(
+ point_in_pixels, original_surface, transformed_point))
+ return false;
+ *transformed_point =
+ gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
+ return true;
}
-gfx::Point RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
+bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) {
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) {
+ if (target_view == this) {
+ *transformed_point = point;
+ return true;
+ }
+
// In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
// but it is not necessary here because the final target view is responsible
// for converting before computing the final transform.
- return delegated_frame_host_->TransformPointToCoordSpaceForView(point,
- target_view);
+ return delegated_frame_host_->TransformPointToCoordSpaceForView(
+ point, target_view, transformed_point);
}
void RenderWidgetHostViewAura::FocusedNodeChanged(
@@ -2094,152 +1688,15 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
}
void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
-
- if (event->type() == ui::ET_SCROLL) {
-#if !defined(OS_WIN)
- // TODO(ananta)
- // Investigate if this is true for Windows 8 Metro ASH as well.
- if (event->finger_count() != 2)
- return;
-#endif
- blink::WebGestureEvent gesture_event = ui::MakeWebGestureEventFlingCancel();
- // Coordinates need to be transferred to the fling cancel gesture only
- // for Surface-targeting to ensure that it is targeted to the correct
- // RenderWidgetHost.
- gesture_event.x = event->x();
- gesture_event.y = event->y();
- blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
- this, &gesture_event, ui::LatencyInfo());
- host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
- this, &mouse_wheel_event);
- } else {
- host_->ForwardGestureEvent(gesture_event);
- host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event,
- *event->latency());
- }
- RecordAction(base::UserMetricsAction("TrackpadScroll"));
- } else if (event->type() == ui::ET_SCROLL_FLING_START ||
- event->type() == ui::ET_SCROLL_FLING_CANCEL) {
- blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
- this, &gesture_event, ui::LatencyInfo());
- } else {
- host_->ForwardGestureEvent(gesture_event);
- }
- if (event->type() == ui::ET_SCROLL_FLING_START)
- RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
- }
-
- event->SetHandled();
+ event_handler_->OnScrollEvent(event);
}
void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
-
- bool had_no_pointer = !pointer_state_.GetPointerCount();
-
- // Update the touch event first.
- if (!pointer_state_.OnTouch(*event)) {
- event->StopPropagation();
- return;
- }
-
- blink::WebTouchEvent touch_event;
- bool handled = selection_controller_->WillHandleTouchEvent(pointer_state_);
- if (handled) {
- event->SetHandled();
- } else {
- touch_event = ui::CreateWebTouchEventFromMotionEvent(
- pointer_state_, event->may_cause_scrolling());
- }
- pointer_state_.CleanupRemovedTouchPoints(*event);
-
- if (handled)
- return;
-
- if (had_no_pointer)
- selection_controller_client_->OnTouchDown();
- if (!pointer_state_.GetPointerCount())
- selection_controller_client_->OnTouchUp();
-
- // It is important to always mark events as being handled asynchronously when
- // they are forwarded. This ensures that the current event does not get
- // processed by the gesture recognizer before events currently awaiting
- // dispatch in the touch queue.
- event->DisableSynchronousHandling();
-
- // Set unchanged touch point to StateStationary for touchmove and
- // touchcancel to make sure only send one ack per WebTouchEvent.
- MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
- this, &touch_event, *event->latency());
- } else {
- ProcessTouchEvent(touch_event, *event->latency());
- }
+ event_handler_->OnTouchEvent(event);
}
void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
- TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
-
- if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
- event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
- event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
- event->SetHandled();
- return;
- }
-
- HandleGestureForTouchSelection(event);
- if (event->handled())
- return;
-
- // Confirm existing composition text on TAP gesture, to make sure the input
- // caret won't be moved with an ongoing composition text.
- if (event->type() == ui::ET_GESTURE_TAP)
- FinishImeCompositionSession();
-
- blink::WebGestureEvent gesture =
- ui::MakeWebGestureEvent(*event, base::Bind(&GetScreenLocationFromEvent));
- if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
- // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
- // event to stop any in-progress flings.
- blink::WebGestureEvent fling_cancel = gesture;
- fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
- fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
- this, &fling_cancel, ui::LatencyInfo());
- } else {
- host_->ForwardGestureEvent(fling_cancel);
- }
- }
-
- if (gesture.type != blink::WebInputEvent::Undefined) {
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
- this, &gesture, *event->latency());
- } else {
- host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
- }
-
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
- event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
- event->type() == ui::ET_GESTURE_SCROLL_END) {
- RecordAction(base::UserMetricsAction("TouchscreenScroll"));
- } else if (event->type() == ui::ET_SCROLL_FLING_START) {
- RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
- }
- }
-
- // If a gesture is not processed by the webpage, then WebKit processes it
- // (e.g. generates synthetic mouse events).
- event->SetHandled();
+ event_handler_->OnGestureEvent(event);
}
////////////////////////////////////////////////////////////////////////////////
@@ -2285,9 +1742,8 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
input_method->SetFocusedTextInputClient(this);
// Often the application can set focus to the view in response to a key
- // down. However the following char event shouldn't be sent to the web
- // page.
- host_->SuppressNextCharEvents();
+ // down. However, the following events shouldn't be sent to the web page.
+ host_->SuppressEventsUntilKeyDown();
}
BrowserAccessibilityManager* manager =
@@ -2381,7 +1837,7 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
if (popup_parent_host_view_) {
DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
popup_parent_host_view_->popup_child_host_view_ == this);
- popup_parent_host_view_->popup_child_host_view_ = NULL;
+ popup_parent_host_view_->SetPopupChild(nullptr);
}
if (popup_child_host_view_) {
DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
@@ -2412,6 +1868,7 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
void RenderWidgetHostViewAura::CreateAuraWindow() {
DCHECK(!window_);
window_ = new aura::Window(this);
+ event_handler_->set_window(window_);
window_observer_.reset(new WindowObserver(this));
aura::client::SetTooltipText(window_, &tooltip_);
@@ -2510,50 +1967,33 @@ bool RenderWidgetHostViewAura::NeedsMouseCapture() {
return false;
}
-void RenderWidgetHostViewAura::FinishImeCompositionSession() {
- if (!has_composition_text_)
- return;
-
- if (!!text_input_manager_ && !!text_input_manager_->GetActiveWidget()) {
- text_input_manager_->GetActiveWidget()->ImeFinishComposingText(false);
- }
- ImeCancelComposition();
-}
-
-void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
- blink::WebMouseEvent* event) {
- // If the mouse has just entered, we must report zero movementX/Y. Hence we
- // reset any global_mouse_position set previously.
- if (event->type == blink::WebInputEvent::MouseEnter ||
- event->type == blink::WebInputEvent::MouseLeave)
- global_mouse_position_.SetPoint(event->globalX, event->globalY);
-
- // Movement is computed by taking the difference of the new cursor position
- // and the previous. Under mouse lock the cursor will be warped back to the
- // center so that we are not limited by clipping boundaries.
- // We do not measure movement as the delta from cursor to center because
- // we may receive more mouse movement events before our warp has taken
- // effect.
- event->movementX = event->globalX - global_mouse_position_.x();
- event->movementY = event->globalY - global_mouse_position_.y();
-
- global_mouse_position_.SetPoint(event->globalX, event->globalY);
-
- // Under mouse lock, coordinates of mouse are locked to what they were when
- // mouse lock was entered.
- if (mouse_locked_) {
- event->x = unlocked_mouse_position_.x();
- event->y = unlocked_mouse_position_.y();
- event->windowX = unlocked_mouse_position_.x();
- event->windowY = unlocked_mouse_position_.y();
- event->globalX = unlocked_global_mouse_position_.x();
- event->globalY = unlocked_global_mouse_position_.y();
+void RenderWidgetHostViewAura::SetTooltipsEnabled(bool enable) {
+ if (enable) {
+ tooltip_disabler_.reset();
} else {
- unlocked_mouse_position_.SetPoint(event->x, event->y);
- unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
+ tooltip_disabler_.reset(
+ new aura::client::ScopedTooltipDisabler(window_->GetRootWindow()));
}
}
+void RenderWidgetHostViewAura::ShowContextMenu(
+ const ContextMenuParams& params) {
+ // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
+ // actually show the disambiguation popup.
+ RenderViewHost* rvh = RenderViewHost::From(host_);
+ if (!rvh)
+ return;
+
+ RenderViewHostDelegate* delegate = rvh->GetDelegate();
+ if (!delegate)
+ return;
+
+ RenderViewHostDelegateView* delegate_view = delegate->GetDelegateView();
+ if (!delegate_view)
+ return;
+ delegate_view->ShowContextMenu(GetFocusedFrame(), params);
+}
+
void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
bool is_visible) {
if (host_->is_hidden() ||
@@ -2593,22 +2033,17 @@ void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
bool RenderWidgetHostViewAura::OnShowContextMenu(
const ContextMenuParams& params) {
#if defined(OS_WIN)
- last_context_menu_params_.reset();
-
- if (params.source_type == ui::MENU_SOURCE_LONG_PRESS) {
- last_context_menu_params_.reset(new ContextMenuParams);
- *last_context_menu_params_ = params;
- return false;
- }
-#endif
+ event_handler_->SetContextMenuParams(params);
+ return params.source_type != ui::MENU_SOURCE_LONG_PRESS;
+#else
return true;
+#endif // defined(OS_WIN)
}
void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
std::unique_ptr<TouchSelectionControllerClientAura> client) {
selection_controller_client_.swap(client);
CreateSelectionController();
- disable_input_event_router_for_testing_ = true;
}
void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
@@ -2664,18 +2099,6 @@ void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
}
}
-bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
- gfx::Rect rect = window_->bounds();
- rect = ConvertRectToScreen(rect);
- int border_x = rect.width() * kMouseLockBorderPercentage / 100;
- int border_y = rect.height() * kMouseLockBorderPercentage / 100;
-
- return global_mouse_position_.x() < rect.x() + border_x ||
- global_mouse_position_.x() > rect.right() - border_x ||
- global_mouse_position_.y() < rect.y() + border_y ||
- global_mouse_position_.y() > rect.bottom() - border_y;
-}
-
void RenderWidgetHostViewAura::AddedToRootWindow() {
window_->GetHost()->AddObserver(this);
UpdateScreenInfo(window_);
@@ -2782,102 +2205,6 @@ void RenderWidgetHostViewAura::CreateSelectionController() {
selection_controller_client_.get(), tsc_config));
}
-void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
- ui::GestureEvent* event) {
- switch (event->type()) {
- case ui::ET_GESTURE_LONG_PRESS:
- if (selection_controller_->WillHandleLongPressEvent(
- event->time_stamp(), event->location_f())) {
- event->SetHandled();
- }
- break;
- case ui::ET_GESTURE_TAP:
- if (selection_controller_->WillHandleTapEvent(
- event->location_f(), event->details().tap_count())) {
- event->SetHandled();
- }
- break;
- case ui::ET_GESTURE_SCROLL_BEGIN:
- selection_controller_client_->OnScrollStarted();
- break;
- case ui::ET_GESTURE_SCROLL_END:
- selection_controller_client_->OnScrollCompleted();
- break;
-#if defined(OS_WIN)
- case ui::ET_GESTURE_LONG_TAP: {
- if (!last_context_menu_params_)
- break;
-
- std::unique_ptr<ContextMenuParams> context_menu_params =
- std::move(last_context_menu_params_);
-
- // On Windows we want to display the context menu when the long press
- // gesture is released. To achieve that, we switch the saved context
- // menu params source type to MENU_SOURCE_TOUCH. This is to ensure that
- // the RenderWidgetHostViewAura::OnShowContextMenu function which is
- // called from the ShowContextMenu call below, does not treat it as
- // a context menu request coming in from the long press gesture.
- DCHECK(context_menu_params->source_type == ui::MENU_SOURCE_LONG_PRESS);
- context_menu_params->source_type = ui::MENU_SOURCE_TOUCH;
-
- RenderViewHostDelegateView* delegate_view =
- GetRenderViewHostDelegateView();
- if (delegate_view)
- delegate_view->ShowContextMenu(GetFocusedFrame(),
- *context_menu_params);
-
- event->SetHandled();
- // WARNING: we may have been deleted during the call to ShowContextMenu().
- break;
- }
-#endif
- default:
- break;
- }
-}
-
-void RenderWidgetHostViewAura::ForwardMouseEventToParent(
- ui::MouseEvent* event) {
- // Needed to propagate mouse event to |window_->parent()->delegate()|, but
- // note that it might be something other than a WebContentsViewAura instance.
- // TODO(pkotwicz): Find a better way of doing this.
- // In fullscreen mode which is typically used by flash, don't forward
- // the mouse events to the parent. The renderer and the plugin process
- // handle these events.
- if (is_fullscreen_)
- return;
-
- if (event->flags() & ui::EF_FROM_TOUCH)
- return;
-
- if (!window_->parent() || !window_->parent()->delegate())
- return;
-
- // Take a copy of |event|, to avoid ConvertLocationToTarget mutating the
- // event.
- std::unique_ptr<ui::Event> event_copy = ui::Event::Clone(*event);
- ui::MouseEvent* mouse_event = static_cast<ui::MouseEvent*>(event_copy.get());
- mouse_event->ConvertLocationToTarget(window_, window_->parent());
- window_->parent()->delegate()->OnMouseEvent(mouse_event);
- if (mouse_event->handled())
- event->SetHandled();
-}
-
-RenderViewHostDelegateView*
-RenderWidgetHostViewAura::GetRenderViewHostDelegateView() {
- // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
- // actually show the disambiguation popup.
- RenderViewHost* rvh = RenderViewHost::From(host_);
- if (!rvh)
- return nullptr;
-
- RenderViewHostDelegate* delegate = rvh->GetDelegate();
- if (!delegate)
- return nullptr;
-
- return delegate->GetDelegateView();
-}
-
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, public:
@@ -2939,10 +2266,6 @@ void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
host_->GetRoutingID(), compositor_frame_sink_id, is_swap_ack, resources));
}
-void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
- host_->ScheduleComposite();
-}
-
void RenderWidgetHostViewAura::SetBeginFrameSource(
cc::BeginFrameSource* source) {
if (begin_frame_source_ && added_frame_observer_) {
@@ -3069,4 +2392,12 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged(
#endif // defined(USE_X11) && !defined(OS_CHROMEOS)
}
+void RenderWidgetHostViewAura::SetPopupChild(
+ RenderWidgetHostViewAura* popup_child_host_view) {
+ popup_child_host_view_ = popup_child_host_view;
+ event_handler_->SetPopupChild(
+ popup_child_host_view,
+ popup_child_host_view ? popup_child_host_view->event_handler() : nullptr);
+}
+
} // namespace content
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 5d99836f4e6..0e2de06e4b0 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
@@ -15,9 +15,9 @@
#include <vector>
#include "base/callback.h"
+#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
@@ -27,6 +27,7 @@
#include "content/browser/compositor/owned_mailbox.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
@@ -35,11 +36,9 @@
#include "ui/aura/client/cursor_client_observer.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_tracker.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/display/display_observer.h"
-#include "ui/events/gestures/motion_event_aura.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/selection_bound.h"
@@ -52,30 +51,21 @@ class ScopedTooltipDisabler;
}
namespace cc {
-class CopyOutputRequest;
-class CopyOutputResult;
class DelegatedFrameData;
}
namespace gfx {
-class Canvas;
class Display;
class Point;
class Rect;
}
-namespace gpu {
-struct Mailbox;
-}
-
namespace ui {
-class CompositorLock;
class InputMethod;
class LocatedEvent;
#if defined(OS_WIN)
class OnScreenKeyboardObserver;
#endif
-class Texture;
class TouchSelectionController;
}
@@ -86,7 +76,6 @@ class LegacyRenderWidgetHostHWND;
class OverscrollController;
class RenderFrameHostImpl;
-class RenderViewHostDelegateView;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
class TouchSelectionControllerClientAura;
@@ -95,6 +84,7 @@ struct TextInputState;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
+ NON_EXPORTED_BASE(public RenderWidgetHostViewEventHandler::Delegate),
public DelegatedFrameHostClient,
public TextInputManager::Observer,
public ui::TextInputClient,
@@ -129,6 +119,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool IsShowing() override;
gfx::Rect GetViewBounds() const override;
void SetBackgroundColor(SkColor color) override;
+ bool IsMouseLocked() override;
gfx::Size GetVisibleViewportSize() const override;
void SetInsets(const gfx::Insets& insets) override;
void FocusedNodeTouched(const gfx::Point& location_dips_screen,
@@ -162,6 +153,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void EndFrameSubscription() override;
bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
gfx::Rect GetBoundsInRootWindow() override;
+ void OnSetNeedsFlushInput() override;
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
void GestureEventAck(const blink::WebGestureEvent& event,
@@ -197,12 +189,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const ui::LatencyInfo& latency) override;
void ProcessGestureEvent(const blink::WebGestureEvent& event,
const ui::LatencyInfo& latency) override;
- gfx::Point TransformPointToLocalCoordSpace(
- const gfx::Point& point,
- const cc::SurfaceId& original_surface) override;
- gfx::Point TransformPointToCoordSpaceForView(
+ bool TransformPointToLocalCoordSpace(const gfx::Point& point,
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) override;
+ bool TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) override;
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) override;
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
@@ -305,18 +298,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SnapToPhysicalPixelBoundary();
- ui::TouchSelectionController* selection_controller() const {
- return selection_controller_.get();
- }
-
- TouchSelectionControllerClientAura* selection_controller_client() const {
- return selection_controller_client_.get();
- }
-
- OverscrollController* overscroll_controller() const {
- return overscroll_controller_.get();
- }
-
// Called when the context menu is about to be displayed.
// Returns true if the context menu should be displayed. We only return false
// on Windows if the context menu is being displayed in response to a long
@@ -332,6 +313,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Exposed for tests.
cc::SurfaceId SurfaceIdForTesting() const override;
+ // RenderWidgetHostViewEventHandler::Delegate:
+ gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const override;
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& event) override;
+ RenderFrameHostImpl* GetFocusedFrame();
+ bool NeedsMouseCapture() override;
+ void SetTooltipsEnabled(bool enable) override;
+ void ShowContextMenu(const ContextMenuParams& params) override;
+ void Shutdown() override;
+
+ RenderWidgetHostViewEventHandler* event_handler() {
+ return event_handler_.get();
+ }
+
protected:
~RenderWidgetHostViewAura() override;
@@ -342,8 +336,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
return delegated_frame_host_.get();
}
- const ui::MotionEventAura& pointer_state() const { return pointer_state_; }
-
private:
friend class InputMethodAuraTestBase;
friend class RenderWidgetHostViewAuraCopyRequestTest;
@@ -409,23 +401,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
ui::InputMethod* GetInputMethod() const;
- // Sends shutdown request.
- void Shutdown();
-
// Returns whether the widget needs an input grab to work properly.
bool NeedsInputGrab();
- // Returns whether the widget needs to grab mouse capture to work properly.
- bool NeedsMouseCapture();
-
- // Confirm existing composition text in the webpage and ask the input method
- // to cancel its ongoing composition session.
- void FinishImeCompositionSession();
-
- // This method computes movementX/Y and keeps track of mouse location for
- // mouse lock on all mouse move events.
- void ModifyEventMovementAndCoords(blink::WebMouseEvent* event);
-
// Sends an IPC to the renderer process to communicate whether or not
// the mouse cursor is visible anywhere on the screen.
void NotifyRendererOfCursorVisibilityState(bool is_visible);
@@ -434,10 +412,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// SchedulePaint() is invoked for |rect|.
void SchedulePaintIfNotInClip(const gfx::Rect& rect, const gfx::Rect& clip);
- // Helper method to determine if, in mouse locked mode, the cursor should be
- // moved to center.
- bool ShouldMoveToCenter();
-
// Called after |window_| is parented to a WindowEventDispatcher.
void AddedToRootWindow();
@@ -457,7 +431,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
int compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) override;
- void DelegatedFrameHostOnLostCompositorResources() override;
void SetBeginFrameSource(cc::BeginFrameSource* source) override;
bool IsAutoResizeEnabled() const override;
@@ -481,34 +454,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Detaches |this| from the input method object.
void DetachFromInputMethod();
- // Before calling RenderWidgetHost::ForwardKeyboardEvent(), this method
- // calls our keybindings handler against the event and send matched
- // edit commands to renderer instead.
- void ForwardKeyboardEvent(const NativeWebKeyboardEvent& event);
-
// Dismisses a Web Popup on a mouse or touch press outside the popup and its
// parent.
void ApplyEventFilterForPopupExit(ui::LocatedEvent* event);
- // Converts |rect| from window coordinate to screen coordinate.
- gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const;
-
// Converts |rect| from screen coordinate to window coordinate.
gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect) const;
- // Helper function to set keyboard focus to the main window.
- void SetKeyboardFocus();
-
- RenderFrameHostImpl* GetFocusedFrame();
-
- // Returns true if the |event| passed in can be forwarded to the renderer.
- bool CanRendererHandleEvent(const ui::MouseEvent* event,
- bool mouse_locked,
- bool selection_popup) const;
-
- // Returns true when we can do SurfaceHitTesting for the event type.
- bool ShouldRouteEvent(const ui::Event* event) const;
-
// Called when the parent window bounds change.
void HandleParentBoundsChanged();
@@ -525,19 +477,16 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Helper function to create a selection controller.
void CreateSelectionController();
- // Performs gesture handling needed for touch text selection. Sets event as
- // handled if it should not be further processed.
- void HandleGestureForTouchSelection(ui::GestureEvent* event);
+ // Used to set the |popup_child_host_view_| on the |popup_parent_host_view_|
+ // and to notify the |event_handler_|.
+ void SetPopupChild(RenderWidgetHostViewAura* popup_child_host_view);
// Forwards a mouse event to this view's parent window delegate.
void ForwardMouseEventToParent(ui::MouseEvent* event);
+ // Adds/Removes frame observer based on state.
void UpdateNeedsBeginFramesInternal();
- // Returns the RenderViewHostDelegateView instance for this view. Returns
- // NULL on failure.
- RenderViewHostDelegateView* GetRenderViewHostDelegateView();
-
// The model object.
RenderWidgetHostImpl* const host_;
@@ -558,9 +507,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// True if in the process of handling a window bounds changed notification.
bool in_bounds_changed_;
- // Is this a fullscreen view?
- bool is_fullscreen_;
-
// Our parent host view, if this is a popup. NULL otherwise.
RenderWidgetHostViewAura* popup_parent_host_view_;
@@ -577,17 +523,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// The cursor for the page. This is passed up from the renderer.
WebCursor current_cursor_;
- // Stores the current state of the active pointers targeting this
- // object.
- ui::MotionEventAura pointer_state_;
-
-
// Indicates if there is onging composition text.
bool has_composition_text_;
- // Whether return characters should be passed on to the RenderWidgetHostImpl.
- bool accept_return_character_;
-
// Current tooltip text.
base::string16 tooltip_;
@@ -598,28 +536,12 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Whether a request for begin frames has been issued.
bool needs_begin_frames_;
+ // Whether a request to flush input has been issued.
+ bool needs_flush_input_;
+
// Whether or not a frame observer has been added.
bool added_frame_observer_;
- // Used to record the last position of the mouse.
- // While the mouse is locked, they store the last known position just as mouse
- // lock was entered.
- // Relative to the upper-left corner of the view.
- gfx::Point unlocked_mouse_position_;
- // Relative to the upper-left corner of the screen.
- gfx::Point unlocked_global_mouse_position_;
- // Last cursor position relative to screen. Used to compute movementX/Y.
- gfx::Point global_mouse_position_;
- // In mouse locked mode, we synthetically move the mouse cursor to the center
- // of the window when it reaches the window borders to avoid it going outside.
- // This flag is used to differentiate between these synthetic mouse move
- // events vs. normal mouse move events.
- bool synthetic_move_sent_;
-
- // Used to track the state of the window we're created from. Only used when
- // created fullscreen.
- std::unique_ptr<aura::WindowTracker> host_tracker_;
-
// Used to track the last cursor visibility update that was sent to the
// renderer via NotifyRendererOfCursorVisibilityState().
enum CursorVisibilityState {
@@ -658,12 +580,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool has_snapped_to_boundary_;
- std::unique_ptr<TouchSelectionControllerClientAura>
- selection_controller_client_;
- std::unique_ptr<ui::TouchSelectionController> selection_controller_;
-
- std::unique_ptr<OverscrollController> overscroll_controller_;
-
// The last scroll offset of the view.
gfx::Vector2dF last_scroll_offset_;
@@ -677,22 +593,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// RenderWidgetHostViewGuest.
bool is_guest_view_hack_;
- // This flag when set ensures that we send over a notification to blink that
- // the current view has focus. Defaults to false.
- bool set_focus_on_mouse_down_or_key_event_;
-
float device_scale_factor_;
- // Allows tests to send gesture events for testing without first sending a
- // corresponding touch sequence, as would be required by
- // RenderWidgetHostInputEventRouter.
- bool disable_input_event_router_for_testing_;
-
// The routing and process IDs for the last RenderWidgetHost which had a
// TextInputState of non-NONE.
int32_t last_active_widget_process_id_;
int32_t last_active_widget_routing_id_;
+ // While this is a ui::EventHandler for targetting, |event_handler_| actually
+ // provides an implementation, and directs events to |host_|.
+ std::unique_ptr<RenderWidgetHostViewEventHandler> event_handler_;
+
base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
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 170ff916eb6..4166fb80a76 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
@@ -40,6 +40,7 @@
#include "content/browser/renderer_host/render_view_host_factory.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_event_handler.h"
#include "content/browser/renderer_host/resize_lock.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/web_contents/web_contents_view_aura.h"
@@ -63,7 +64,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/test/aura_test_helper.h"
@@ -84,6 +85,7 @@
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/events/gestures/motion_event_aura.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/test/event_generator.h"
@@ -248,8 +250,12 @@ class TestWindowObserver : public aura::WindowObserver {
DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
};
-class FakeSurfaceDamageObserver : public cc::SurfaceDamageObserver {
+class FakeSurfaceObserver : public cc::SurfaceObserver {
public:
+ void OnSurfaceCreated(const cc::SurfaceId& surface_id,
+ const gfx::Size& frame,
+ float device_scale_factor) override {}
+
void OnSurfaceDamaged(const cc::SurfaceId& id, bool* changed) override {
*changed = true;
}
@@ -370,7 +376,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->LocalFrameIdForTesting();
}
- bool HasFrameData() const { return !GetLocalFrameId().is_null(); }
+ bool HasFrameData() const { return GetLocalFrameId().is_valid(); }
bool released_front_lock_active() const {
return GetDelegatedFrameHost()->ReleasedFrontLockActiveForTesting();
@@ -391,7 +397,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
};
const ui::MotionEventAura& pointer_state_for_test() {
- return pointer_state();
+ return event_handler()->pointer_state();
}
bool can_create_resize_lock_;
@@ -435,6 +441,39 @@ class MockWindowObserver : public aura::WindowObserver {
MOCK_METHOD2(OnDelegatedFrameDamage, void(aura::Window*, const gfx::Rect&));
};
+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();
+ }
+
+ // Extracts |latency_info| for wheel event, and stores it in
+ // |lastWheelOrTouchEventLatencyInfo|.
+ void ForwardWheelEventWithLatencyInfo(
+ const blink::WebMouseWheelEvent& wheel_event,
+ const ui::LatencyInfo& ui_latency) override {
+ RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(wheel_event,
+ ui_latency);
+ lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency);
+ }
+
+ // Extracts |latency_info| for touch event, and stores it in
+ // |lastWheelOrTouchEventLatencyInfo|.
+ void ForwardTouchEventWithLatencyInfo(
+ const blink::WebTouchEvent& touch_event,
+ const ui::LatencyInfo& ui_latency) override {
+ RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(touch_event,
+ ui_latency);
+ lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency);
+ }
+
+ ui::LatencyInfo lastWheelOrTouchEventLatencyInfo;
+};
+
const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
base::PickleIterator iter(message);
const char* data;
@@ -450,14 +489,14 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
public:
RenderWidgetHostViewAuraTest()
: widget_host_uses_shutdown_to_destroy_(false),
- is_guest_view_hack_(false),
- browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
+ is_guest_view_hack_(false) {}
void SetUpEnvironment() {
ImageTransportFactory::InitializeForUnitTests(
std::unique_ptr<ImageTransportFactory>(
new NoTransportImageTransportFactory));
- aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
+ aura_test_helper_.reset(
+ new aura::test::AuraTestHelper(base::MessageLoopForUI::current()));
aura_test_helper_->SetUp(
ImageTransportFactory::GetInstance()->GetContextFactory());
new wm::DefaultActivationClient(aura_test_helper_->root_window());
@@ -482,8 +521,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
routing_id = process_host_->GetNextRoutingID();
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- widget_host_ = new RenderWidgetHostImpl(delegates_.back().get(),
- process_host_, routing_id, false);
+ widget_host_ = new MockRenderWidgetHostImpl(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_);
@@ -514,8 +553,6 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
browser_context_.reset();
aura_test_helper_->TearDown();
- message_loop_.task_runner()->DeleteSoon(FROM_HERE,
- browser_context_.release());
base::RunLoop().RunUntilIdle();
ImageTransportFactory::Terminate();
}
@@ -544,7 +581,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
void SendInputEventACK(WebInputEvent::Type type,
InputEventAckState ack_result) {
DCHECK(!WebInputEvent::isTouchEventType(type));
- InputEventAck ack(type, ack_result);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result);
InputHostMsg_HandleInputEvent_ACK response(0, ack);
widget_host_->OnMessageReceived(response);
}
@@ -553,7 +590,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
InputEventAckState ack_result,
uint32_t event_id) {
DCHECK(WebInputEvent::isTouchEventType(type));
- InputEventAck ack(type, ack_result, event_id);
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result,
+ event_id);
InputHostMsg_HandleInputEvent_ACK response(0, ack);
widget_host_->OnMessageReceived(response);
}
@@ -629,8 +667,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
bool is_guest_view_hack_;
- base::MessageLoopForUI message_loop_;
- BrowserThreadImpl browser_thread_for_ui_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<aura::test::AuraTestHelper> aura_test_helper_;
std::unique_ptr<BrowserContext> browser_context_;
std::vector<std::unique_ptr<MockRenderWidgetHostDelegate>> delegates_;
@@ -643,7 +680,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
// Tests should set these to nullptr if they've already triggered their
// destruction.
- RenderWidgetHostImpl* widget_host_;
+ MockRenderWidgetHostImpl* widget_host_;
FakeRenderWidgetHostViewAura* view_;
IPC::TestSink* sink_;
@@ -1303,9 +1340,9 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
// Ack'ing the outstanding event should flush the pending touch queue.
- InputEventAck ack(blink::WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- press.unique_event_id());
+ InputEventAck ack(
+ InputEventAckSource::COMPOSITOR_THREAD, blink::WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, press.unique_event_id());
widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
@@ -1475,7 +1512,11 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
EXPECT_EQ("200x200", view_->GetPhysicalBackingSize().ToString());
// Extra ScreenInfoChanged message for |parent_view_|.
- EXPECT_EQ(0u, sink_->message_count());
+ // Changing the device scale factor triggers the
+ // RenderWidgetHostViewAura::OnDisplayMetricsChanged() observer callback,
+ // which sends a ViewMsg_Resize::ID message to the renderer.
+ EXPECT_EQ(1u, sink_->message_count());
+ EXPECT_EQ(ViewMsg_Resize::ID, sink_->GetMessageAt(0)->type());
auto view_delegate = static_cast<MockRenderWidgetHostDelegate*>(
static_cast<RenderWidgetHostImpl*>(view_->GetRenderWidgetHost())
->delegate());
@@ -1486,7 +1527,8 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
aura_test_helper_->test_screen()->SetDeviceScaleFactor(1.0f);
// Extra ScreenInfoChanged message for |parent_view_|.
- EXPECT_EQ(0u, sink_->message_count());
+ EXPECT_EQ(1u, sink_->message_count());
+ EXPECT_EQ(ViewMsg_Resize::ID, sink_->GetMessageAt(0)->type());
EXPECT_EQ(1.0f, view_delegate->get_last_device_scale_factor());
EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString());
}
@@ -1642,10 +1684,10 @@ cc::CompositorFrame MakeDelegatedFrame(float scale_factor,
// client in response to the swap. This test verifies that the returned
// resources are indeed reported as being in response to a swap.
TEST_F(RenderWidgetHostViewAuraTest, ResettingCompositorReturnsResources) {
- FakeSurfaceDamageObserver damage_observer;
+ FakeSurfaceObserver manager_observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
- manager->AddObserver(&damage_observer);
+ manager->AddObserver(&manager_observer);
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
@@ -1673,7 +1715,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ResettingCompositorReturnsResources) {
EXPECT_EQ(0u, std::get<0>(params)); // compositor_frame_sink_id
EXPECT_TRUE(std::get<1>(params)); // is_swap_ack
}
- manager->RemoveObserver(&damage_observer);
+ manager->RemoveObserver(&manager_observer);
}
// This test verifies that returned resources do not require a pending ack.
@@ -1709,10 +1751,10 @@ TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// This test verifies that when the compositor_frame_sink_id changes, then
// DelegateFrameHost returns compositor resources without a swap ack.
TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
- FakeSurfaceDamageObserver damage_observer;
+ FakeSurfaceObserver manager_observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
- manager->AddObserver(&damage_observer);
+ manager->AddObserver(&manager_observer);
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
@@ -1766,7 +1808,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
EXPECT_EQ(true, std::get<1>(params)); // is_swap_ack
}
- manager->RemoveObserver(&damage_observer);
+ manager->RemoveObserver(&manager_observer);
}
// Resizing in fullscreen mode should send the up-to-date screen info.
@@ -1874,7 +1916,7 @@ TEST_F(RenderWidgetHostViewAuraTest, MirrorLayers) {
view_->GetNativeView(), false /* sync_bounds */));
cc::SurfaceId id = view_->GetDelegatedFrameHost()->SurfaceIdForTesting();
- if (!id.is_null()) {
+ if (id.is_valid()) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
cc::Surface* surface = manager->GetSurfaceForId(id);
@@ -2005,7 +2047,7 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)));
cc::SurfaceId surface_id = view_->surface_id();
- if (surface_id.is_null()) {
+ if (!surface_id.is_valid()) {
// No frame ack yet.
EXPECT_EQ(0u, sink_->message_count());
} else {
@@ -2521,6 +2563,28 @@ TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
EXPECT_NE(surface_id, view_->surface_id());
}
+TEST_F(RenderWidgetHostViewAuraTest, SourceEventTypeExistsInLatencyInfo) {
+ // WHEEL source exists.
+ ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(2, 2), ui::EventTimeForNow(),
+ 0, 0, 0, 0, 0, 2);
+ view_->OnScrollEvent(&scroll);
+ EXPECT_EQ(widget_host_->lastWheelOrTouchEventLatencyInfo.source_event_type(),
+ ui::SourceEventType::WHEEL);
+
+ // TOUCH source exists.
+ ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), 0,
+ ui::EventTimeForNow());
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0,
+ ui::EventTimeForNow());
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0,
+ ui::EventTimeForNow());
+ view_->OnTouchEvent(&press);
+ view_->OnTouchEvent(&move);
+ EXPECT_EQ(widget_host_->lastWheelOrTouchEventLatencyInfo.source_event_type(),
+ ui::SourceEventType::TOUCH);
+ view_->OnTouchEvent(&release);
+}
+
class RenderWidgetHostViewAuraCopyRequestTest
: public RenderWidgetHostViewAuraShutdownTest {
public:
@@ -2577,7 +2641,7 @@ class RenderWidgetHostViewAuraCopyRequestTest
1, MakeDelegatedFrame(1.f, view_rect_.size(), view_rect_));
cc::SurfaceId surface_id =
view_->GetDelegatedFrameHost()->SurfaceIdForTesting();
- if (!surface_id.is_null())
+ if (surface_id.is_valid())
view_->GetDelegatedFrameHost()->WillDrawSurface(
surface_id.local_frame_id(), view_rect_);
ASSERT_TRUE(view_->last_copy_request_);
@@ -4068,24 +4132,6 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardMouseEvent) {
view_ = nullptr;
}
-// Tests the RenderWidgetHostImpl sends the correct surface ID namespace to
-// the renderer process.
-TEST_F(RenderWidgetHostViewAuraTest, FrameSinkIdInitialized) {
- gfx::Size size(5, 5);
-
- const IPC::Message* msg =
- sink_->GetUniqueMessageMatching(ViewMsg_SetFrameSinkId::ID);
- EXPECT_TRUE(msg);
- ViewMsg_SetFrameSinkId::Param params;
- ViewMsg_SetFrameSinkId::Read(msg, &params);
- view_->InitAsChild(nullptr);
- view_->Show();
- view_->SetSize(size);
- view_->OnSwapCompositorFrame(0,
- MakeDelegatedFrame(1.f, size, gfx::Rect(size)));
- EXPECT_EQ(view_->GetFrameSinkId(), std::get<0>(params));
-}
-
// This class provides functionality to test a RenderWidgetHostViewAura
// instance which has been hooked up to a test RenderViewHost instance and
// a WebContents instance.
@@ -4443,8 +4489,8 @@ TEST_F(InputMethodResultAuraTest, CommitText) {
// is in response to a mouse click during an ongoing composition.
TEST_F(InputMethodResultAuraTest, FinishImeCompositionSession) {
base::Closure ime_finish_session_call =
- base::Bind(&RenderWidgetHostViewAura::FinishImeCompositionSession,
- base::Unretained(tab_view()));
+ base::Bind(&RenderWidgetHostViewEventHandler::FinishImeCompositionSession,
+ base::Unretained(tab_view()->event_handler()));
for (auto index : active_view_sequence_) {
ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
SetHasCompositionTextToTrue();
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 28b36981dba..6408c68278f 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
@@ -32,7 +32,8 @@ const int kFlushInputRateInUs = 16666;
}
RenderWidgetHostViewBase::RenderWidgetHostViewBase()
- : popup_type_(blink::WebPopupTypeNone),
+ : is_fullscreen_(false),
+ popup_type_(blink::WebPopupTypeNone),
background_color_(SK_ColorWHITE),
mouse_locked_(false),
showing_context_menu_(false),
@@ -42,7 +43,6 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
#endif
current_device_scale_factor_(0),
current_display_rotation_(display::Display::ROTATE_0),
- pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
text_input_manager_(nullptr),
renderer_frame_number_(0),
weak_factory_(this) {
@@ -80,9 +80,8 @@ RenderWidgetHost* RenderWidgetHostViewBase::GetRenderWidgetHost() const {
void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
// Note: RenderWidgetHostInputEventRouter is an observer, and uses the
// following notification to remove this view from its surface owners map.
- FOR_EACH_OBSERVER(RenderWidgetHostViewBaseObserver,
- observers_,
- OnRenderWidgetHostViewBaseDestroyed(this));
+ for (auto& observer : observers_)
+ observer.OnRenderWidgetHostViewBaseDestroyed(this);
// All observers are required to disconnect after they are notified.
DCHECK(!observers_.might_have_observers());
}
@@ -95,6 +94,10 @@ void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
background_color_ = color;
}
+SkColor RenderWidgetHostViewBase::background_color() {
+ return background_color_;
+}
+
void RenderWidgetHostViewBase::SetBackgroundColorToDefault() {
SetBackgroundColor(SK_ColorWHITE);
}
@@ -110,7 +113,7 @@ gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
display.device_scale_factor());
}
-bool RenderWidgetHostViewBase::DoTopControlsShrinkBlinkSize() const {
+bool RenderWidgetHostViewBase::DoBrowserControlsShrinkBlinkSize() const {
return false;
}
@@ -440,17 +443,20 @@ gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF(
gfx::ToRoundedPoint(point)));
}
-gfx::Point RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) {
- return point;
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) {
+ *transformed_point = point;
+ return true;
}
-gfx::Point RenderWidgetHostViewBase::TransformPointToCoordSpaceForView(
+bool RenderWidgetHostViewBase::TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) {
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) {
NOTREACHED();
- return point;
+ return true;
}
bool RenderWidgetHostViewBase::IsRenderWidgetHostViewGuest() {
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 7ea34285895..88e7a046c20 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
@@ -42,7 +42,6 @@
class SkBitmap;
-struct AccessibilityHostMsg_EventParams;
struct ViewHostMsg_SelectionBounds_Params;
namespace media {
@@ -91,6 +90,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// RenderWidgetHostView implementation.
RenderWidgetHost* GetRenderWidgetHost() const override;
void SetBackgroundColor(SkColor color) override;
+ SkColor background_color() override;
void SetBackgroundColorToDefault() final;
bool GetBackgroundOpaque() override;
ui::TextInputClient* GetTextInputClient() override;
@@ -161,9 +161,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// Whether or not Blink's viewport size should be shrunk by the height of the
// URL-bar.
- virtual bool DoTopControlsShrinkBlinkSize() const;
+ virtual bool DoBrowserControlsShrinkBlinkSize() const;
- // The height of the URL-bar top controls.
+ // The height of the URL-bar browser controls.
virtual float GetTopControlsHeight() const;
// The height of the bottom bar.
@@ -257,18 +257,21 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// RenderWidget and needs to be translated to viewport coordinates for the
// root RWHV, in which case this method is called on the root RWHV with the
// out-of-process iframe's SurfaceId.
- // This does not transform points between surfaces where one does not
- // contain the other. To transform between sibling surfaces, the point must
- // be transformed to the root's coordinate space as an intermediate step.
- virtual gfx::Point TransformPointToLocalCoordSpace(
+ // Returns false when this attempts to transform a point between coordinate
+ // spaces of surfaces where one does not contain the other. To transform
+ // between sibling surfaces, the point must be transformed to the root's
+ // coordinate space as an intermediate step.
+ virtual bool TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface);
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point);
// Transform a point that is in the coordinate space for the current
// RenderWidgetHostView to the coordinate space of the target_view.
- virtual gfx::Point TransformPointToCoordSpaceForView(
+ virtual bool TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view);
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point);
// TODO(kenrb, wjmaclean): This is a temporary subclass identifier for
// RenderWidgetHostViewGuests that is needed for special treatment during
@@ -413,16 +416,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
void AddObserver(RenderWidgetHostViewBaseObserver* observer);
void RemoveObserver(RenderWidgetHostViewBaseObserver* observer);
- // Exposed for testing.
- virtual bool IsChildFrameForTesting() const;
- virtual cc::SurfaceId SurfaceIdForTesting() const;
-
- protected:
- // Interface class only, do not construct.
- RenderWidgetHostViewBase();
-
- void NotifyObserversAboutShutdown();
-
// Returns a reference to the current instance of TextInputManager. The
// reference is obtained from RenderWidgetHostDelegate. The first time a non-
// null reference is obtained, its value is cached in |text_input_manager_|
@@ -435,6 +428,21 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// |text_input_manager_|.
TextInputManager* GetTextInputManager();
+ bool is_fullscreen() { return is_fullscreen_; }
+
+ // Exposed for testing.
+ virtual bool IsChildFrameForTesting() const;
+ virtual cc::SurfaceId SurfaceIdForTesting() const;
+
+ protected:
+ // Interface class only, do not construct.
+ RenderWidgetHostViewBase();
+
+ void NotifyObserversAboutShutdown();
+
+ // Is this a fullscreen view?
+ bool is_fullscreen_;
+
// Whether this view is a popup and what kind of popup it is (select,
// autofill...).
blink::WebPopupType popup_type_;
@@ -474,10 +482,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// The orientation of the display the renderer is currently on.
display::Display::Rotation current_display_rotation_;
- // Whether pinch-to-zoom should be enabled and pinch events forwarded to the
- // renderer.
- bool pinch_zoom_enabled_;
-
// A reference to current TextInputManager instance this RWHV is registered
// with. This is initially nullptr until the first time the view calls
// GetTextInputManager(). It also becomes nullptr when TextInputManager is
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
new file mode 100644
index 00000000000..2adb005ff4b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -0,0 +1,873 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
+
+#include "base/metrics/user_metrics_action.h"
+#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
+#include "content/browser/renderer_host/overscroll_controller.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_delegate_view.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/text_input_manager.h"
+#include "content/common/content_switches_internal.h"
+#include "content/common/site_isolation_policy.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/user_metrics.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/events/blink/blink_event_util.h"
+#include "ui/events/blink/web_input_event.h"
+#include "ui/touch_selection/touch_selection_controller.h"
+
+#if defined(OS_WIN)
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/common/context_menu_params.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/display/screen.h"
+#endif // defined(OS_WIN)
+
+namespace {
+
+// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
+// the border of the view, in order to get valid movement information. However,
+// forcing the cursor back to the center of the view after each mouse move
+// doesn't work well. It reduces the frequency of useful mouse move messages
+// significantly. Therefore, we move the cursor to the center of the view only
+// if it approaches the border. |kMouseLockBorderPercentage| specifies the width
+// of the border area, in percentage of the corresponding dimension.
+const int kMouseLockBorderPercentage = 15;
+
+#if defined(OS_WIN)
+// A callback function for EnumThreadWindows to enumerate and dismiss
+// any owned popup windows.
+BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
+ const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
+
+ if (::IsWindowVisible(window)) {
+ const HWND owner = ::GetWindow(window, GW_OWNER);
+ if (toplevel_hwnd == owner) {
+ ::PostMessage(window, WM_CANCELMODE, 0, 0);
+ }
+ }
+
+ return TRUE;
+}
+#endif // defined(OS_WIN)
+
+gfx::Point GetScreenLocationFromEvent(const ui::LocatedEvent& event) {
+ aura::Window* root =
+ static_cast<aura::Window*>(event.target())->GetRootWindow();
+ aura::client::ScreenPositionClient* spc =
+ aura::client::GetScreenPositionClient(root);
+ if (!spc)
+ return event.root_location();
+
+ gfx::Point screen_location(event.root_location());
+ spc->ConvertPointToScreen(root, &screen_location);
+ return screen_location;
+}
+
+bool IsFractionalScaleFactor(float scale_factor) {
+ return (scale_factor - static_cast<int>(scale_factor)) > 0;
+}
+
+// We don't mark these as handled so that they're sent back to the
+// DefWindowProc so it can generate WM_APPCOMMAND as necessary.
+bool IsXButtonUpEvent(const ui::MouseEvent* event) {
+#if defined(OS_WIN)
+ switch (event->native_event().message) {
+ case WM_XBUTTONUP:
+ case WM_NCXBUTTONUP:
+ return true;
+ }
+#endif
+ return false;
+}
+
+// Reset unchanged touch points to StateStationary for touchmove and
+// touchcancel.
+void MarkUnchangedTouchPointsAsStationary(blink::WebTouchEvent* event,
+ int changed_touch_id) {
+ if (event->type == blink::WebInputEvent::TouchMove ||
+ event->type == blink::WebInputEvent::TouchCancel) {
+ for (size_t i = 0; i < event->touchesLength; ++i) {
+ if (event->touches[i].id != changed_touch_id)
+ event->touches[i].state = blink::WebTouchPoint::StateStationary;
+ }
+ }
+}
+
+bool NeedsInputGrab(content::RenderWidgetHostViewBase* view) {
+ if (!view)
+ return false;
+ return view->GetPopupType() == blink::WebPopupTypePage;
+}
+
+} // namespace
+
+namespace content {
+
+RenderWidgetHostViewEventHandler::Delegate::Delegate()
+ : selection_controller_client_(nullptr),
+ selection_controller_(nullptr),
+ overscroll_controller_(nullptr) {}
+
+RenderWidgetHostViewEventHandler::Delegate::~Delegate() {}
+
+RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler(
+ RenderWidgetHostImpl* host,
+ RenderWidgetHostViewBase* host_view,
+ Delegate* delegate)
+ : accept_return_character_(false),
+ disable_input_event_router_for_testing_(false),
+ mouse_locked_(false),
+ pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
+ set_focus_on_mouse_down_or_key_event_(false),
+ synthetic_move_sent_(false),
+ host_(RenderWidgetHostImpl::From(host)),
+ host_view_(host_view),
+ popup_child_host_view_(nullptr),
+ popup_child_event_handler_(nullptr),
+ delegate_(delegate),
+ window_(nullptr) {}
+
+RenderWidgetHostViewEventHandler::~RenderWidgetHostViewEventHandler() {}
+
+void RenderWidgetHostViewEventHandler::SetPopupChild(
+ RenderWidgetHostViewBase* popup_child_host_view,
+ ui::EventHandler* popup_child_event_handler) {
+ popup_child_host_view_ = popup_child_host_view;
+ popup_child_event_handler_ = popup_child_event_handler;
+}
+
+void RenderWidgetHostViewEventHandler::TrackHost(
+ aura::Window* reference_window) {
+ if (!reference_window)
+ return;
+ DCHECK(!host_tracker_);
+ host_tracker_.reset(new aura::WindowTracker);
+ host_tracker_->Add(reference_window);
+}
+
+#if defined(OS_WIN)
+void RenderWidgetHostViewEventHandler::SetContextMenuParams(
+ const ContextMenuParams& params) {
+ last_context_menu_params_.reset();
+ if (params.source_type == ui::MENU_SOURCE_LONG_PRESS) {
+ last_context_menu_params_.reset(new ContextMenuParams);
+ *last_context_menu_params_ = params;
+ }
+}
+
+void RenderWidgetHostViewEventHandler::UpdateMouseLockRegion() {
+ RECT window_rect =
+ display::Screen::GetScreen()
+ ->DIPToScreenRectInWindow(window_, window_->GetBoundsInScreen())
+ .ToRECT();
+ ::ClipCursor(&window_rect);
+}
+#endif
+
+bool RenderWidgetHostViewEventHandler::LockMouse() {
+ aura::Window* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return false;
+
+ if (mouse_locked_)
+ return true;
+
+ mouse_locked_ = true;
+#if !defined(OS_WIN)
+ window_->SetCapture();
+#else
+ UpdateMouseLockRegion();
+#endif
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window);
+ if (cursor_client) {
+ cursor_client->HideCursor();
+ cursor_client->LockCursor();
+ }
+
+ if (ShouldMoveToCenter()) {
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
+ }
+ delegate_->SetTooltipsEnabled(false);
+ return true;
+}
+
+void RenderWidgetHostViewEventHandler::UnlockMouse() {
+ delegate_->SetTooltipsEnabled(true);
+
+ aura::Window* root_window = window_->GetRootWindow();
+ if (!mouse_locked_ || !root_window)
+ return;
+
+ mouse_locked_ = false;
+
+ if (window_->HasCapture())
+ window_->ReleaseCapture();
+
+#if defined(OS_WIN)
+ ::ClipCursor(NULL);
+#endif
+
+ // Ensure that the global mouse position is updated here to its original
+ // value. If we don't do this then the synthesized mouse move which is posted
+ // after the cursor is moved ends up getting a large movement delta which is
+ // not what sites expect. The delta is computed in the
+ // ModifyEventMovementAndCoords function.
+ global_mouse_position_ = unlocked_global_mouse_position_;
+ window_->MoveCursorTo(unlocked_mouse_position_);
+
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window);
+ if (cursor_client) {
+ cursor_client->UnlockCursor();
+ cursor_client->ShowCursor();
+ }
+ host_->LostMouseLock();
+}
+
+void RenderWidgetHostViewEventHandler::OnKeyEvent(ui::KeyEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnKeyEvent");
+
+ if (NeedsInputGrab(popup_child_host_view_)) {
+ popup_child_event_handler_->OnKeyEvent(event);
+ if (event->handled())
+ return;
+ }
+
+ // We need to handle the Escape key for Pepper Flash.
+ if (host_view_->is_fullscreen() && event->key_code() == ui::VKEY_ESCAPE) {
+ // Focus the window we were created from.
+ if (host_tracker_.get() && !host_tracker_->windows().empty()) {
+ aura::Window* host = *(host_tracker_->windows().begin());
+ aura::client::FocusClient* client = aura::client::GetFocusClient(host);
+ if (client) {
+ // Calling host->Focus() may delete |this|. We create a local observer
+ // for that. In that case we exit without further access to any members.
+ auto local_tracker = std::move(host_tracker_);
+ local_tracker->Add(window_);
+ host->Focus();
+ if (!local_tracker->Contains(window_)) {
+ event->SetHandled();
+ return;
+ }
+ }
+ }
+ delegate_->Shutdown();
+ host_tracker_.reset();
+ } else {
+ if (event->key_code() == ui::VKEY_RETURN) {
+ // Do not forward return key release events if no press event was handled.
+ if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
+ return;
+ // Accept return key character events between press and release events.
+ accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
+ }
+
+ // Call SetKeyboardFocus() for not only ET_KEY_PRESSED but also
+ // ET_KEY_RELEASED. If a user closed the hotdog menu with ESC key press,
+ // we need to notify focus to Blink on ET_KEY_RELEASED for ESC key.
+ SetKeyboardFocus();
+ // We don't have to communicate with an input method here.
+ NativeWebKeyboardEvent webkit_event(*event);
+ delegate_->ForwardKeyboardEvent(webkit_event);
+ }
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnMouseEvent");
+ ForwardMouseEventToParent(event);
+ // TODO(mgiuca): Return if event->handled() returns true. This currently
+ // breaks drop-down lists which means something is incorrectly setting
+ // event->handled to true (http://crbug.com/577983).
+
+ if (mouse_locked_) {
+ HandleMouseEventWhileLocked(event);
+ return;
+ }
+
+ // As the overscroll is handled during scroll events from the trackpad, the
+ // RWHVA window is transformed by the overscroll controller. This transform
+ // triggers a synthetic mouse-move event to be generated (by the aura
+ // RootWindow). But this event interferes with the overscroll gesture. So,
+ // ignore such synthetic mouse-move events if an overscroll gesture is in
+ // progress.
+ OverscrollController* overscroll_controller =
+ delegate_->overscroll_controller();
+ if (overscroll_controller &&
+ overscroll_controller->overscroll_mode() != OVERSCROLL_NONE &&
+ event->flags() & ui::EF_IS_SYNTHESIZED &&
+ (event->type() == ui::ET_MOUSE_ENTERED ||
+ event->type() == ui::ET_MOUSE_EXITED ||
+ event->type() == ui::ET_MOUSE_MOVED)) {
+ event->StopPropagation();
+ return;
+ }
+
+ if (event->type() == ui::ET_MOUSEWHEEL) {
+#if defined(OS_WIN)
+ // We get mouse wheel/scroll messages even if we are not in the foreground.
+ // So here we check if we have any owned popup windows in the foreground and
+ // dismiss them.
+ aura::WindowTreeHost* host = window_->GetHost();
+ if (host) {
+ HWND parent = host->GetAcceleratedWidget();
+ HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
+ EnumThreadWindows(GetCurrentThreadId(), DismissOwnedPopups,
+ reinterpret_cast<LPARAM>(toplevel_hwnd));
+ }
+#endif
+ blink::WebMouseWheelEvent mouse_wheel_event =
+ ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
+ base::Bind(&GetScreenLocationFromEvent));
+ if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) {
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
+ host_view_, &mouse_wheel_event, *event->latency());
+ } else {
+ ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
+ }
+ }
+ } else {
+ bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
+ if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
+ !(event->flags() & ui::EF_FROM_TOUCH)) {
+ // Confirm existing composition text on mouse press, to make sure
+ // the input caret won't be moved with an ongoing composition text.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ FinishImeCompositionSession();
+
+ blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(
+ *event, base::Bind(&GetScreenLocationFromEvent));
+ ModifyEventMovementAndCoords(*event, &mouse_event);
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
+ host_view_, &mouse_event, *event->latency());
+ } else {
+ ProcessMouseEvent(mouse_event, *event->latency());
+ }
+
+ // Ensure that we get keyboard focus on mouse down as a plugin window may
+ // have grabbed keyboard focus.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ SetKeyboardFocus();
+ }
+ }
+
+ switch (event->type()) {
+ case ui::ET_MOUSE_PRESSED:
+ window_->SetCapture();
+ break;
+ case ui::ET_MOUSE_RELEASED:
+ if (!delegate_->NeedsMouseCapture())
+ window_->ReleaseCapture();
+ break;
+ default:
+ break;
+ }
+
+ if (!IsXButtonUpEvent(event))
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnScrollEvent");
+
+ if (event->type() == ui::ET_SCROLL) {
+#if !defined(OS_WIN)
+ // TODO(ananta)
+ // Investigate if this is true for Windows 8 Metro ASH as well.
+ if (event->finger_count() != 2)
+ return;
+#endif
+ blink::WebGestureEvent gesture_event = ui::MakeWebGestureEventFlingCancel();
+ // Coordinates need to be transferred to the fling cancel gesture only
+ // for Surface-targeting to ensure that it is targeted to the correct
+ // RenderWidgetHost.
+ gesture_event.x = event->x();
+ gesture_event.y = event->y();
+ blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
+ *event, base::Bind(&GetScreenLocationFromEvent));
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ host_view_, &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
+ host_view_, &mouse_wheel_event, *event->latency());
+ } else {
+ host_->ForwardGestureEvent(gesture_event);
+ host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event,
+ *event->latency());
+ }
+ RecordAction(base::UserMetricsAction("TrackpadScroll"));
+ } else if (event->type() == ui::ET_SCROLL_FLING_START ||
+ event->type() == ui::ET_SCROLL_FLING_CANCEL) {
+ blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent(
+ *event, base::Bind(&GetScreenLocationFromEvent));
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ host_view_, &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ } else {
+ host_->ForwardGestureEvent(gesture_event);
+ }
+ if (event->type() == ui::ET_SCROLL_FLING_START)
+ RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
+ }
+
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewEventHandler::OnTouchEvent(ui::TouchEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnTouchEvent");
+
+ bool had_no_pointer = !pointer_state_.GetPointerCount();
+
+ // Update the touch event first.
+ if (!pointer_state_.OnTouch(*event)) {
+ event->StopPropagation();
+ return;
+ }
+
+ blink::WebTouchEvent touch_event;
+ bool handled =
+ delegate_->selection_controller()->WillHandleTouchEvent(pointer_state_);
+ if (handled) {
+ event->SetHandled();
+ } else {
+ touch_event = ui::CreateWebTouchEventFromMotionEvent(
+ pointer_state_, event->may_cause_scrolling());
+ }
+ pointer_state_.CleanupRemovedTouchPoints(*event);
+
+ if (handled)
+ return;
+
+ if (had_no_pointer)
+ delegate_->selection_controller_client()->OnTouchDown();
+ if (!pointer_state_.GetPointerCount())
+ delegate_->selection_controller_client()->OnTouchUp();
+
+ // It is important to always mark events as being handled asynchronously when
+ // they are forwarded. This ensures that the current event does not get
+ // processed by the gesture recognizer before events currently awaiting
+ // dispatch in the touch queue.
+ event->DisableSynchronousHandling();
+
+ // Set unchanged touch point to StateStationary for touchmove and
+ // touchcancel to make sure only send one ack per WebTouchEvent.
+ MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
+ host_view_, &touch_event, *event->latency());
+ } else {
+ ProcessTouchEvent(touch_event, *event->latency());
+ }
+}
+
+void RenderWidgetHostViewEventHandler::OnGestureEvent(ui::GestureEvent* event) {
+ TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnGestureEvent");
+
+ if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
+ event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
+ event->type() == ui::ET_GESTURE_PINCH_END) &&
+ !pinch_zoom_enabled_) {
+ event->SetHandled();
+ return;
+ }
+
+ HandleGestureForTouchSelection(event);
+ if (event->handled())
+ return;
+
+ // Confirm existing composition text on TAP gesture, to make sure the input
+ // caret won't be moved with an ongoing composition text.
+ if (event->type() == ui::ET_GESTURE_TAP)
+ FinishImeCompositionSession();
+
+ blink::WebGestureEvent gesture =
+ ui::MakeWebGestureEvent(*event, base::Bind(&GetScreenLocationFromEvent));
+ if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
+ // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
+ // event to stop any in-progress flings.
+ blink::WebGestureEvent fling_cancel = gesture;
+ fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
+ fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ host_view_, &fling_cancel,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ } else {
+ host_->ForwardGestureEvent(fling_cancel);
+ }
+ }
+
+ if (gesture.type != blink::WebInputEvent::Undefined) {
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ host_view_, &gesture, *event->latency());
+ } else {
+ host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
+ }
+
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
+ event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
+ event->type() == ui::ET_GESTURE_SCROLL_END) {
+ RecordAction(base::UserMetricsAction("TouchscreenScroll"));
+ } else if (event->type() == ui::ET_SCROLL_FLING_START) {
+ RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
+ }
+ }
+
+ // If a gesture is not processed by the webpage, then WebKit processes it
+ // (e.g. generates synthetic mouse events).
+ event->SetHandled();
+}
+
+bool RenderWidgetHostViewEventHandler::CanRendererHandleEvent(
+ const ui::MouseEvent* event,
+ bool mouse_locked,
+ bool selection_popup) const {
+ if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
+ return false;
+
+ if (event->type() == ui::ET_MOUSE_EXITED) {
+ if (mouse_locked || selection_popup)
+ return false;
+#if defined(OS_WIN)
+ // Don't forward the mouse leave message which is received when the context
+ // menu is displayed by the page. This confuses the page and causes state
+ // changes.
+ if (host_view_->IsShowingContextMenu())
+ return false;
+#endif
+ return true;
+ }
+
+#if defined(OS_WIN)
+ // Renderer cannot handle WM_XBUTTON or NC events.
+ switch (event->native_event().message) {
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ case WM_XBUTTONDBLCLK:
+ case WM_NCMOUSELEAVE:
+ case WM_NCMOUSEMOVE:
+ case WM_NCLBUTTONDOWN:
+ case WM_NCLBUTTONUP:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCRBUTTONUP:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCMBUTTONUP:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_NCXBUTTONDOWN:
+ case WM_NCXBUTTONUP:
+ case WM_NCXBUTTONDBLCLK:
+ return false;
+ default:
+ break;
+ }
+#elif defined(USE_X11)
+ // Renderer only supports standard mouse buttons, so ignore programmable
+ // buttons.
+ switch (event->type()) {
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED: {
+ const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
+ ui::EF_MIDDLE_MOUSE_BUTTON |
+ ui::EF_RIGHT_MOUSE_BUTTON;
+ return (event->flags() & kAllowedButtons) != 0;
+ }
+ default:
+ break;
+ }
+#endif
+ return true;
+}
+
+void RenderWidgetHostViewEventHandler::FinishImeCompositionSession() {
+ if (!host_view_->GetTextInputClient()->HasCompositionText())
+ return;
+
+ TextInputManager* text_input_manager = host_view_->GetTextInputManager();
+ if (!!text_input_manager && !!text_input_manager->GetActiveWidget())
+ text_input_manager->GetActiveWidget()->ImeFinishComposingText(false);
+ host_view_->ImeCancelComposition();
+}
+
+void RenderWidgetHostViewEventHandler::ForwardMouseEventToParent(
+ ui::MouseEvent* event) {
+ // Needed to propagate mouse event to |window_->parent()->delegate()|, but
+ // note that it might be something other than a WebContentsViewAura instance.
+ // TODO(pkotwicz): Find a better way of doing this.
+ // In fullscreen mode which is typically used by flash, don't forward
+ // the mouse events to the parent. The renderer and the plugin process
+ // handle these events.
+ if (host_view_->is_fullscreen())
+ return;
+
+ if (event->flags() & ui::EF_FROM_TOUCH)
+ return;
+
+ if (!window_->parent() || !window_->parent()->delegate())
+ return;
+
+ // Take a copy of |event|, to avoid ConvertLocationToTarget mutating the
+ // event.
+ std::unique_ptr<ui::Event> event_copy = ui::Event::Clone(*event);
+ ui::MouseEvent* mouse_event = static_cast<ui::MouseEvent*>(event_copy.get());
+ mouse_event->ConvertLocationToTarget(window_, window_->parent());
+ window_->parent()->delegate()->OnMouseEvent(mouse_event);
+ if (mouse_event->handled())
+ event->SetHandled();
+}
+
+void RenderWidgetHostViewEventHandler::HandleGestureForTouchSelection(
+ ui::GestureEvent* event) {
+ switch (event->type()) {
+ case ui::ET_GESTURE_LONG_PRESS:
+ if (delegate_->selection_controller()->WillHandleLongPressEvent(
+ event->time_stamp(), event->location_f())) {
+ event->SetHandled();
+ }
+ break;
+ case ui::ET_GESTURE_TAP:
+ if (delegate_->selection_controller()->WillHandleTapEvent(
+ event->location_f(), event->details().tap_count())) {
+ event->SetHandled();
+ }
+ break;
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ delegate_->selection_controller_client()->OnScrollStarted();
+ break;
+ case ui::ET_GESTURE_SCROLL_END:
+ delegate_->selection_controller_client()->OnScrollCompleted();
+ break;
+#if defined(OS_WIN)
+ case ui::ET_GESTURE_LONG_TAP: {
+ if (!last_context_menu_params_)
+ break;
+
+ std::unique_ptr<ContextMenuParams> context_menu_params =
+ std::move(last_context_menu_params_);
+
+ // On Windows we want to display the context menu when the long press
+ // gesture is released. To achieve that, we switch the saved context
+ // menu params source type to MENU_SOURCE_TOUCH. This is to ensure that
+ // the RenderWidgetHostViewBase::OnShowContextMenu function which is
+ // called from the ShowContextMenu call below, does not treat it as
+ // a context menu request coming in from the long press gesture.
+ DCHECK(context_menu_params->source_type == ui::MENU_SOURCE_LONG_PRESS);
+ context_menu_params->source_type = ui::MENU_SOURCE_TOUCH;
+
+ delegate_->ShowContextMenu(*context_menu_params);
+ event->SetHandled();
+ // WARNING: we may have been deleted during the call to ShowContextMenu().
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+}
+
+void RenderWidgetHostViewEventHandler::HandleMouseEventWhileLocked(
+ ui::MouseEvent* event) {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window_->GetRootWindow());
+
+ DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
+
+ if (event->type() == ui::ET_MOUSEWHEEL) {
+ blink::WebMouseWheelEvent mouse_wheel_event =
+ ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
+ base::Bind(&GetScreenLocationFromEvent));
+ if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
+ host_->ForwardWheelEvent(mouse_wheel_event);
+ return;
+ }
+
+ gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
+
+ // If we receive non client mouse messages while we are in the locked state
+ // it probably means that the mouse left the borders of our window and
+ // needs to be moved back to the center.
+ if (event->flags() & ui::EF_IS_NON_CLIENT) {
+ // TODO(jonross): ideally this would not be done for mus (crbug.com/621412)
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(center);
+ return;
+ }
+
+ blink::WebMouseEvent mouse_event =
+ ui::MakeWebMouseEvent(*event, base::Bind(&GetScreenLocationFromEvent));
+
+ bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_DRAGGED) &&
+ mouse_event.x == center.x() &&
+ mouse_event.y == center.y();
+
+ // For fractional scale factors, the conversion from pixels to dip and
+ // vice versa could result in off by 1 or 2 errors which hurts us because
+ // we want to avoid sending the artificial move to center event to the
+ // renderer. Sending the move to center to the renderer cause the cursor
+ // to bounce around the center of the screen leading to the lock operation
+ // not working correctly.
+ // Workaround is to treat a mouse move or drag event off by at most 2 px
+ // from the center as a move to center event.
+ if (synthetic_move_sent_ &&
+ IsFractionalScaleFactor(host_view_->current_device_scale_factor())) {
+ if (event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_DRAGGED) {
+ if ((abs(mouse_event.x - center.x()) <= 2) &&
+ (abs(mouse_event.y - center.y()) <= 2)) {
+ is_move_to_center_event = true;
+ }
+ }
+ }
+
+ ModifyEventMovementAndCoords(*event, &mouse_event);
+
+ bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
+ if (should_not_forward) {
+ synthetic_move_sent_ = false;
+ } else {
+ // Check if the mouse has reached the border and needs to be centered.
+ if (ShouldMoveToCenter()) {
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(center);
+ }
+ bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
+ // Forward event to renderer.
+ if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
+ !(event->flags() & ui::EF_FROM_TOUCH)) {
+ host_->ForwardMouseEvent(mouse_event);
+ // Ensure that we get keyboard focus on mouse down as a plugin window
+ // may have grabbed keyboard focus.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ SetKeyboardFocus();
+ }
+ }
+}
+
+void RenderWidgetHostViewEventHandler::ModifyEventMovementAndCoords(
+ const ui::MouseEvent& ui_mouse_event,
+ blink::WebMouseEvent* event) {
+ // If the mouse has just entered, we must report zero movementX/Y. Hence we
+ // reset any global_mouse_position set previously.
+ if (ui_mouse_event.type() == ui::ET_MOUSE_ENTERED ||
+ ui_mouse_event.type() == ui::ET_MOUSE_EXITED) {
+ global_mouse_position_.SetPoint(event->globalX, event->globalY);
+ }
+
+ // Movement is computed by taking the difference of the new cursor position
+ // and the previous. Under mouse lock the cursor will be warped back to the
+ // center so that we are not limited by clipping boundaries.
+ // We do not measure movement as the delta from cursor to center because
+ // we may receive more mouse movement events before our warp has taken
+ // effect.
+ event->movementX = event->globalX - global_mouse_position_.x();
+ event->movementY = event->globalY - global_mouse_position_.y();
+
+ global_mouse_position_.SetPoint(event->globalX, event->globalY);
+
+ // Under mouse lock, coordinates of mouse are locked to what they were when
+ // mouse lock was entered.
+ if (mouse_locked_) {
+ event->x = unlocked_mouse_position_.x();
+ event->y = unlocked_mouse_position_.y();
+ event->windowX = unlocked_mouse_position_.x();
+ event->windowY = unlocked_mouse_position_.y();
+ event->globalX = unlocked_global_mouse_position_.x();
+ event->globalY = unlocked_global_mouse_position_.y();
+ } else {
+ unlocked_mouse_position_.SetPoint(event->x, event->y);
+ unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
+ }
+}
+
+void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
+#if defined(OS_WIN)
+ if (window_ && window_->delegate()->CanFocus()) {
+ aura::WindowTreeHost* host = window_->GetHost();
+ if (host) {
+ gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget();
+ if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE))
+ ::SetFocus(hwnd);
+ }
+ }
+#endif
+ // TODO(wjmaclean): can host_ ever be null?
+ if (host_ && set_focus_on_mouse_down_or_key_event_) {
+ set_focus_on_mouse_down_or_key_event_ = false;
+ host_->Focus();
+ }
+}
+
+bool RenderWidgetHostViewEventHandler::ShouldMoveToCenter() {
+ gfx::Rect rect = window_->bounds();
+ rect = delegate_->ConvertRectToScreen(rect);
+ int border_x = rect.width() * kMouseLockBorderPercentage / 100;
+ int border_y = rect.height() * kMouseLockBorderPercentage / 100;
+
+ return global_mouse_position_.x() < rect.x() + border_x ||
+ global_mouse_position_.x() > rect.right() - border_x ||
+ global_mouse_position_.y() < rect.y() + border_y ||
+ global_mouse_position_.y() > rect.bottom() - border_y;
+}
+
+bool RenderWidgetHostViewEventHandler::ShouldRouteEvent(
+ const ui::Event* event) const {
+ // We should route an event in two cases:
+ // 1) Mouse events are routed only if cross-process frames are possible.
+ // 2) Touch events are always routed. In the absence of a BrowserPlugin
+ // we expect the routing to always send the event to this view. If
+ // one or more BrowserPlugins are present, then the event may be targeted
+ // to one of them, or this view. This allows GuestViews to have access to
+ // them while still forcing pinch-zoom to be handled by the top-level
+ // frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but
+ // it should be a simple extension to modify RenderWidgetHostViewChildFrame
+ // in a similar manner to RenderWidgetHostViewGuest.
+ bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() &&
+ !disable_input_event_router_for_testing_;
+ // 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;
+}
+
+void RenderWidgetHostViewEventHandler::ProcessMouseEvent(
+ const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardMouseEventWithLatencyInfo(event, latency);
+}
+
+void RenderWidgetHostViewEventHandler::ProcessMouseWheelEvent(
+ const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardWheelEventWithLatencyInfo(event, latency);
+}
+
+void RenderWidgetHostViewEventHandler::ProcessTouchEvent(
+ const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardTouchEventWithLatencyInfo(event, latency);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
new file mode 100644
index 00000000000..dd263108542
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
@@ -0,0 +1,253 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_EVENT_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_EVENT_HANDLER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "ui/aura/window_tracker.h"
+#include "ui/events/event_handler.h"
+#include "ui/events/gestures/motion_event_aura.h"
+#include "ui/events/latency_info.h"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace blink {
+class WebMouseEvent;
+class WebMouseWheelEvent;
+class WebTouchEvent;
+} // namespace blink
+
+namespace ui {
+class TextInputClient;
+class TouchSelectionController;
+}
+
+namespace content {
+struct ContextMenuParams;
+class OverscrollController;
+class RenderViewHost;
+class RenderWidgetHostImpl;
+class RenderWidgetHostViewBase;
+class TouchSelectionControllerClientAura;
+
+// Provides an implementation of ui::EventHandler for use with
+// RenderWidgetHostViewBase. A delegate is required in order to provide platform
+// specific functionality.
+//
+// After processing events they will be forwarded to the provided
+// RenderWidgetHostImpl.
+//
+// This does not implement ui::TextInputClient, which some
+// RenderWidgetHostViewBase classes do.
+// RenderWidgetHostViewEventHandler::Delegate implementations may have
+// overlapping functionality with the ui::TextInputClient.
+class CONTENT_EXPORT RenderWidgetHostViewEventHandler
+ : public ui::EventHandler {
+ public:
+ // An interface to provide platform specific logic needed for event handling.
+ class Delegate {
+ public:
+ Delegate();
+
+ // Converts |rect| from window coordinate to screen coordinate.
+ virtual gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const = 0;
+ // Call keybindings handler against the event and send matched edit commands
+ // to the renderer instead.
+ virtual void ForwardKeyboardEvent(const NativeWebKeyboardEvent& event) = 0;
+ // Returns whether the widget needs to grab mouse capture to work properly.
+ virtual bool NeedsMouseCapture() = 0;
+ virtual void SetTooltipsEnabled(bool enable) = 0;
+ virtual void ShowContextMenu(const ContextMenuParams& params) = 0;
+ // Sends shutdown request.
+ virtual void Shutdown() = 0;
+
+ ui::TouchSelectionController* selection_controller() const {
+ return selection_controller_.get();
+ }
+
+ TouchSelectionControllerClientAura* selection_controller_client() const {
+ return selection_controller_client_.get();
+ }
+
+ OverscrollController* overscroll_controller() const {
+ return overscroll_controller_.get();
+ }
+
+ protected:
+ virtual ~Delegate();
+
+ std::unique_ptr<TouchSelectionControllerClientAura>
+ selection_controller_client_;
+ std::unique_ptr<ui::TouchSelectionController> selection_controller_;
+ std::unique_ptr<OverscrollController> overscroll_controller_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ RenderWidgetHostViewEventHandler(RenderWidgetHostImpl* host,
+ RenderWidgetHostViewBase* host_view,
+ Delegate* delegate);
+ ~RenderWidgetHostViewEventHandler() override;
+
+ // Set child popup's host view, and event handler, in order to redirect input.
+ void SetPopupChild(RenderWidgetHostViewBase* popup_child_host_view,
+ ui::EventHandler* popup_child_event_handler);
+ // Begin tracking a host window, such as when RenderWidgetHostViewBase is
+ // fullscreen.
+ void TrackHost(aura::Window* reference_window);
+
+#if defined(OS_WIN)
+ // Sets the ContextMenuParams when a context menu is triggered. Required for
+ // subsequent event processing.
+ void SetContextMenuParams(const ContextMenuParams& params);
+
+ // Updates the cursor clip region. Used for mouse locking.
+ void UpdateMouseLockRegion();
+#endif // defined(OS_WIN)
+
+ bool accept_return_character() { return accept_return_character_; }
+ void disable_input_event_router_for_testing() {
+ disable_input_event_router_for_testing_ = true;
+ }
+ bool mouse_locked() { return mouse_locked_; }
+ const ui::MotionEventAura& pointer_state() const { return pointer_state_; }
+ void set_focus_on_mouse_down_or_key_event(
+ bool focus_on_mouse_down_or_key_event) {
+ set_focus_on_mouse_down_or_key_event_ = focus_on_mouse_down_or_key_event;
+ }
+ void set_window(aura::Window* window) { window_ = window; }
+
+ // Lock/Unlock processing of future mouse events.
+ bool LockMouse();
+ void UnlockMouse();
+
+ // ui::EventHandler:
+ void OnKeyEvent(ui::KeyEvent* event) override;
+ void OnMouseEvent(ui::MouseEvent* event) override;
+ void OnScrollEvent(ui::ScrollEvent* event) override;
+ void OnTouchEvent(ui::TouchEvent* event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(InputMethodResultAuraTest,
+ FinishImeCompositionSession);
+ // Returns true if the |event| passed in can be forwarded to the renderer.
+ bool CanRendererHandleEvent(const ui::MouseEvent* event,
+ bool mouse_locked,
+ bool selection_popup) const;
+
+ // Confirm existing composition text in the webpage and ask the input method
+ // to cancel its ongoing composition session.
+ void FinishImeCompositionSession();
+
+ // Forwards a mouse event to this view's parent window delegate.
+ void ForwardMouseEventToParent(ui::MouseEvent* event);
+
+ // Performs gesture handling needed for touch text selection. Sets event as
+ // handled if it should not be further processed.
+ void HandleGestureForTouchSelection(ui::GestureEvent* event);
+
+ // Handles mouse event handling while the mouse is locked via LockMouse.
+ void HandleMouseEventWhileLocked(ui::MouseEvent* event);
+
+ // This method computes movementX/Y and keeps track of mouse location for
+ // mouse lock on all mouse move events.
+ // |ui_mouse_event| contains the mouse event received.
+ // |event| contains the WebMouseEvent being modified.
+ void ModifyEventMovementAndCoords(const ui::MouseEvent& ui_mouse_event,
+ blink::WebMouseEvent* event);
+
+ // Helper function to set keyboard focus to the main window.
+ void SetKeyboardFocus();
+
+ // Helper method to determine if, in mouse locked mode, the cursor should be
+ // moved to center.
+ bool ShouldMoveToCenter();
+
+ // Returns true when we can do SurfaceHitTesting for the event type.
+ bool ShouldRouteEvent(const ui::Event* event) const;
+
+ // Directs events to the |host_|.
+ void ProcessMouseEvent(const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency);
+ void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency);
+ void ProcessTouchEvent(const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency);
+
+ // Whether return characters should be passed on to the RenderWidgetHostImpl.
+ bool accept_return_character_;
+
+ // Allows tests to send gesture events for testing without first sending a
+ // corresponding touch sequence, as would be required by
+ // RenderWidgetHostInputEventRouter.
+ bool disable_input_event_router_for_testing_;
+
+ // While the mouse is locked, the cursor is hidden from the user. Mouse events
+ // are still generated. However, the position they report is the last known
+ // mouse position just as mouse lock was entered; the movement they report
+ // indicates what the change in position of the mouse would be had it not been
+ // locked.
+ bool mouse_locked_;
+
+ // Whether pinch-to-zoom should be enabled and pinch events forwarded to the
+ // renderer.
+ bool pinch_zoom_enabled_;
+
+ // This flag when set ensures that we send over a notification to blink that
+ // the current view has focus. Defaults to false.
+ bool set_focus_on_mouse_down_or_key_event_;
+
+ // Used to track the state of the window we're created from. Only used when
+ // created fullscreen.
+ std::unique_ptr<aura::WindowTracker> host_tracker_;
+
+ // Used to record the last position of the mouse.
+ // While the mouse is locked, they store the last known position just as mouse
+ // lock was entered.
+ // Relative to the upper-left corner of the view.
+ gfx::Point unlocked_mouse_position_;
+ // Relative to the upper-left corner of the screen.
+ gfx::Point unlocked_global_mouse_position_;
+ // Last cursor position relative to screen. Used to compute movementX/Y.
+ gfx::Point global_mouse_position_;
+ // In mouse locked mode, we synthetically move the mouse cursor to the center
+ // of the window when it reaches the window borders to avoid it going outside.
+ // This flag is used to differentiate between these synthetic mouse move
+ // events vs. normal mouse move events.
+ bool synthetic_move_sent_;
+ // Stores the current state of the active pointers targeting this
+ // object.
+ ui::MotionEventAura pointer_state_;
+
+#if defined(OS_WIN)
+ // Contains a copy of the last context menu request parameters. Only set when
+ // we receive a request to show the context menu on a long press.
+ std::unique_ptr<ContextMenuParams> last_context_menu_params_;
+#endif // defined(OS_WIN)
+
+ // The following are not owned. They should outlive |this|
+ RenderWidgetHostImpl* const host_;
+ // Should create |this| and own it.
+ RenderWidgetHostViewBase* const host_view_;
+ // Optional, used to redirect events to a popup and associated handler.
+ RenderWidgetHostViewBase* popup_child_host_view_;
+ ui::EventHandler* popup_child_event_handler_;
+ Delegate* const delegate_;
+ aura::Window* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewEventHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_EVENT_HANDLER_H_
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 0c83402489d..ccb3e90c908 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
@@ -320,6 +320,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool LockMouse() override;
void UnlockMouse() override;
+ void OnSetNeedsFlushInput() override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
@@ -340,12 +341,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const ui::LatencyInfo& latency) override;
void ProcessGestureEvent(const blink::WebGestureEvent& event,
const ui::LatencyInfo& latency) override;
- gfx::Point TransformPointToLocalCoordSpace(
+ bool TransformPointToLocalCoordSpace(const gfx::Point& point,
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) override;
+ bool TransformPointToCoordSpaceForView(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) override;
- gfx::Point TransformPointToCoordSpaceForView(
- const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) override;
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) override;
// TextInputManager::Observer implementation.
void OnUpdateTextInputStateCalled(TextInputManager* text_input_manager,
@@ -456,7 +458,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
int compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) override;
- void BrowserCompositorMacOnLostCompositorResources() override;
void BrowserCompositorMacSendBeginFrame(
const cc::BeginFrameArgs& args) override;
@@ -500,6 +501,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Get the focused view that should be used for retrieving the text selection.
RenderWidgetHostViewBase* GetFocusedViewForTextSelection();
+ // Adds/Removes frame observer based on state.
+ void UpdateNeedsBeginFramesInternal();
+
// The associated view. This is weak and is inserted into the view hierarchy
// to own this RenderWidgetHostViewMac object. Set to nil at the start of the
// destructor.
@@ -545,6 +549,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
+ // Whether a request for begin frames has been issued.
+ bool needs_begin_frames_;
+
+ // Whether a request to flush input has been issued.
+ bool needs_flush_input_;
+
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
index c81f211e3a5..93d929c4f2b 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
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#import <Carbon/Carbon.h>
#import <objc/runtime.h>
#include <OpenGL/gl.h>
#include <QuartzCore/QuartzCore.h>
@@ -67,7 +68,7 @@
#include "gpu/ipc/common/gpu_messages.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_mac.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/cocoa/animation_utils.h"
#import "ui/base/cocoa/appkit_utils.h"
@@ -97,6 +98,7 @@ using content::RenderFrameHost;
using content::RenderViewHost;
using content::RenderViewHostImpl;
using content::RenderWidgetHostImpl;
+using content::RenderWidgetHostView;
using content::RenderWidgetHostViewMac;
using content::RenderWidgetHostViewMacEditCommandHelper;
using content::TextInputClientMac;
@@ -118,7 +120,7 @@ BOOL EventIsReservedBySystem(NSEvent* event) {
return helper->map()->IsEventReserved(event);
}
-RenderWidgetHostViewMac* GetRenderWidgetHostViewToUse(
+RenderWidgetHostView* GetRenderWidgetHostViewToUse(
RenderWidgetHostViewMac* render_widget_host_view) {
WebContents* web_contents = render_widget_host_view->GetWebContents();
if (!web_contents)
@@ -131,8 +133,7 @@ RenderWidgetHostViewMac* GetRenderWidgetHostViewToUse(
guest_manager->GetFullPageGuest(web_contents);
if (!guest)
return render_widget_host_view;
- return static_cast<RenderWidgetHostViewMac*>(
- guest->GetRenderWidgetHostView());
+ return guest->GetRenderWidgetHostView();
}
} // namespace
@@ -409,12 +410,11 @@ void RenderWidgetHostViewMac::
is_swap_ack, resources));
}
-void RenderWidgetHostViewMac::BrowserCompositorMacOnLostCompositorResources() {
- render_widget_host_->ScheduleComposite();
-}
-
void RenderWidgetHostViewMac::BrowserCompositorMacSendBeginFrame(
const cc::BeginFrameArgs& args) {
+ needs_flush_input_ = false;
+ render_widget_host_->FlushInput();
+ UpdateNeedsBeginFramesInternal();
render_widget_host_->Send(
new ViewMsg_BeginFrame(render_widget_host_->GetRoutingID(), args));
}
@@ -451,6 +451,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
allow_pause_for_resize_or_repaint_(true),
is_guest_view_hack_(is_guest_view_hack),
fullscreen_parent_host_view_(nullptr),
+ needs_flush_input_(false),
weak_factory_(this) {
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_|
// goes away. Since we autorelease it, our caller must put
@@ -484,14 +485,29 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
}
RenderViewHost* rvh = RenderViewHost::From(render_widget_host_);
+ bool needs_begin_frames = true;
+
if (rvh) {
// TODO(mostynb): actually use prefs. Landing this as a separate CL
// first to rebaseline some unreliable layout tests.
ignore_result(rvh->GetWebkitPreferences());
+ needs_begin_frames = !rvh->GetDelegate()->IsNeverVisible();
}
if (GetTextInputManager())
GetTextInputManager()->AddObserver(this);
+
+ // Because of the way Mac pumps messages during resize, (see the code
+ // in RenderMessageFilter::OnMessageReceived), SetNeedsBeginFrame
+ // messages are not delayed on Mac. This leads to creation-time
+ // raciness where renderer sends a SetNeedsBeginFrame(true) before
+ // the renderer host is created to recieve it.
+ //
+ // Any renderer that will produce frames needs to have begin frames sent to
+ // it. So unless it is never visible, start this value at true here to avoid
+ // startup raciness and decrease latency.
+ needs_begin_frames_ = needs_begin_frames;
+ UpdateNeedsBeginFramesInternal();
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
@@ -879,13 +895,25 @@ void RenderWidgetHostViewMac::OnUpdateTextInputStateCalled(
if (!did_update_state)
return;
+ // |updated_view| is the last view to change its TextInputState which can be
+ // used to start/stop monitoring composition info when it has a focused
+ // editable text input field.
+ RenderWidgetHost* widgetHost = updated_view->GetRenderWidgetHost();
+
+ // We might end up here when |updated_view| has had active TextInputState and
+ // then got destroyed. In that case, |updated_view->GetRenderWidgetHost()|
+ // returns nullptr.
+ if (!widgetHost)
+ return;
+
// Set the monitor state based on the text input focus state.
const bool has_focus = HasFocus();
const TextInputState* state = text_input_manager->GetTextInputState();
bool need_monitor_composition =
has_focus && state && state->type != ui::TEXT_INPUT_TYPE_NONE;
- Send(new InputMsg_RequestCompositionUpdate(
- render_widget_host_->GetRoutingID(), false /* immediate request */,
+
+ widgetHost->Send(new InputMsg_RequestCompositionUpdate(
+ widgetHost->GetRoutingID(), false /* immediate request */,
need_monitor_composition));
if (has_focus) {
@@ -1187,7 +1215,18 @@ void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) {
}
void RenderWidgetHostViewMac::SetNeedsBeginFrames(bool needs_begin_frames) {
- browser_compositor_->SetNeedsBeginFrames(needs_begin_frames);
+ needs_begin_frames_ = needs_begin_frames;
+ UpdateNeedsBeginFramesInternal();
+}
+
+void RenderWidgetHostViewMac::OnSetNeedsFlushInput() {
+ needs_flush_input_ = true;
+ UpdateNeedsBeginFramesInternal();
+}
+
+void RenderWidgetHostViewMac::UpdateNeedsBeginFramesInternal() {
+ browser_compositor_->SetNeedsBeginFrames(needs_begin_frames_ ||
+ needs_flush_input_);
}
void RenderWidgetHostViewMac::KillSelf() {
@@ -1490,7 +1529,7 @@ cc::FrameSinkId RenderWidgetHostViewMac::FrameSinkIdAtPoint(
// It is possible that the renderer has not yet produced a surface, in which
// case we return our current namespace.
- if (id.is_null())
+ if (!id.is_valid())
return GetFrameSinkId();
return id.frame_sink_id();
}
@@ -1530,27 +1569,36 @@ void RenderWidgetHostViewMac::ProcessGestureEvent(
render_widget_host_->ForwardGestureEventWithLatencyInfo(event, latency);
}
-gfx::Point RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
const gfx::Point& point,
- const cc::SurfaceId& original_surface) {
- gfx::Point transformed_point;
+ const cc::SurfaceId& original_surface,
+ gfx::Point* transformed_point) {
// Transformations use physical pixels rather than DIP, so conversion
// is necessary.
float scale_factor = display::Screen::GetScreen()
->GetDisplayNearestWindow(cocoa_view_)
.device_scale_factor();
gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
- transformed_point =
- browser_compositor_->GetDelegatedFrameHost()
- ->TransformPointToLocalCoordSpace(point_in_pixels, original_surface);
- return gfx::ConvertPointToDIP(scale_factor, transformed_point);
+ if (!browser_compositor_->GetDelegatedFrameHost()
+ ->TransformPointToLocalCoordSpace(point_in_pixels, original_surface,
+ transformed_point))
+ return false;
+ *transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
+ return true;
}
-gfx::Point RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
+bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
const gfx::Point& point,
- RenderWidgetHostViewBase* target_view) {
+ RenderWidgetHostViewBase* target_view,
+ gfx::Point* transformed_point) {
+ if (target_view == this) {
+ *transformed_point = point;
+ return true;
+ }
+
return browser_compositor_->GetDelegatedFrameHost()
- ->TransformPointToCoordSpaceForView(point, target_view);
+ ->TransformPointToCoordSpaceForView(point, target_view,
+ transformed_point);
}
bool RenderWidgetHostViewMac::Send(IPC::Message* message) {
@@ -1873,14 +1921,14 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
WebMouseEvent enterEvent = WebMouseEventBuilder::Build(theEvent, self);
enterEvent.type = WebInputEvent::MouseMove;
enterEvent.button = WebMouseEvent::Button::NoButton;
+ ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
if (renderWidgetHostView_->ShouldRouteEvent(enterEvent)) {
renderWidgetHostView_->render_widget_host_->delegate()
->GetInputEventRouter()
- ->RouteMouseEvent(renderWidgetHostView_.get(), &enterEvent);
+ ->RouteMouseEvent(renderWidgetHostView_.get(), &enterEvent,
+ latency_info);
} else {
- ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
- 0, 0);
renderWidgetHostView_->ProcessMouseEvent(enterEvent, latency_info);
}
}
@@ -1911,13 +1959,13 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
}
WebMouseEvent event = WebMouseEventBuilder::Build(theEvent, self);
+ ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
if (renderWidgetHostView_->ShouldRouteEvent(event)) {
renderWidgetHostView_->render_widget_host_->delegate()
->GetInputEventRouter()
- ->RouteMouseEvent(renderWidgetHostView_.get(), &event);
+ ->RouteMouseEvent(renderWidgetHostView_.get(), &event, latency_info);
} else {
- ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
renderWidgetHostView_->ProcessMouseEvent(event, latency_info);
}
}
@@ -2248,7 +2296,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(
event, self);
webEvent.railsMode = mouseWheelFilter_.UpdateRailsMode(webEvent);
- ui::LatencyInfo latency_info;
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
renderWidgetHostView_->render_widget_host_->
ForwardWheelEventWithLatencyInfo(webEvent, latency_info);
@@ -2340,14 +2388,34 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
- (void)showLookUpDictionaryOverlayFromRange:(NSRange)range
targetView:(NSView*)targetView {
+ RenderWidgetHostImpl* widgetHost = renderWidgetHostView_->render_widget_host_;
+ if (!widgetHost || !widgetHost->delegate())
+ return;
+ widgetHost = widgetHost->delegate()->GetFocusedRenderWidgetHost(widgetHost);
+
+ if (!widgetHost)
+ return;
+
+ // TODO(ekaramad): The position reported by the renderer is with respect to
+ // |widgetHost|'s coordinate space with y-axis inverted to conform to AppKit
+ // coordinate system. The point will need to be transformed into root view's
+ // coordinate system (RenderWidgetHostViewMac in this case). However, since
+ // the callback is invoked on IO thread it will require some thread hopping to
+ // do so. For this reason, for now, we accept this non-ideal way of fixing the
+ // point offset manually from the view bounds. This should be revisited when
+ // fixing issues in TextInputClientMac (https://crbug.com/643233).
+ gfx::Rect root_box = renderWidgetHostView_->GetViewBounds();
+ gfx::Rect view_box = widgetHost->GetView()->GetViewBounds();
+
TextInputClientMac::GetInstance()->GetStringFromRange(
- renderWidgetHostView_->render_widget_host_, range,
- ^(NSAttributedString* string, NSPoint baselinePoint) {
+ widgetHost, range, ^(NSAttributedString* string, NSPoint baselinePoint) {
+ baselinePoint.x += view_box.origin().x() - root_box.origin().x();
+ baselinePoint.y +=
+ root_box.bottom_left().y() - view_box.bottom_left().y();
[self showLookUpDictionaryOverlayInternal:string
baselinePoint:baselinePoint
targetView:targetView];
- }
- );
+ });
}
- (void)showLookUpDictionaryOverlayAtPoint:(NSPoint)point {
@@ -2447,13 +2515,14 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
if (renderWidgetHostView_->render_widget_host_) {
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
webEvent.railsMode = mouseWheelFilter_.UpdateRailsMode(webEvent);
+ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
if (renderWidgetHostView_->ShouldRouteEvent(webEvent)) {
renderWidgetHostView_->render_widget_host_->delegate()
->GetInputEventRouter()
- ->RouteMouseWheelEvent(renderWidgetHostView_.get(), &webEvent);
+ ->RouteMouseWheelEvent(renderWidgetHostView_.get(), &webEvent,
+ latency_info);
} else {
- ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
renderWidgetHostView_->ProcessMouseWheelEvent(webEvent, latency_info);
}
}
@@ -2965,6 +3034,12 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
return rect;
}
+- (NSRange)selectedRange {
+ if (selectedRange_.location == NSNotFound)
+ return NSMakeRange(NSNotFound, 0);
+ return selectedRange_;
+}
+
- (NSRange)markedRange {
// An input method calls this method to check if an application really has
// a text being composed when hasMarkedText call returns true.
@@ -2977,9 +3052,17 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
actualRange:(NSRangePointer)actualRange {
- // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery.
+ // Prepare |actualRange| as if the proposed range is invalid. If it is valid,
+ // then |actualRange| will be updated again.
if (actualRange)
- *actualRange = range;
+ *actualRange = NSMakeRange(NSNotFound, 0);
+
+ // The caller of this method is allowed to pass nonsensical ranges. These
+ // can't even be converted into gfx::Ranges.
+ if (range.location == NSNotFound || range.length == 0)
+ return nil;
+ if (range.length >= std::numeric_limits<NSUInteger>::max() - range.location)
+ return nil;
const gfx::Range requested_range(range);
if (requested_range.is_reversed())
@@ -2997,15 +3080,16 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
expected_range = gfx::Range(offset, offset + expected_text->size());
}
- if (!expected_range.Contains(requested_range))
+ gfx::Range actual_range = expected_range.Intersect(requested_range);
+ if (!actual_range.IsValid())
return nil;
// Gets the raw bytes to avoid unnecessary string copies for generating
// NSString.
const base::char16* bytes =
- &(*expected_text)[requested_range.start() - expected_range.start()];
+ &(*expected_text)[actual_range.start() - expected_range.start()];
// Avoid integer overflow.
- base::CheckedNumeric<size_t> requested_len = requested_range.length();
+ base::CheckedNumeric<size_t> requested_len = actual_range.length();
requested_len *= sizeof(base::char16);
NSUInteger bytes_len = base::strict_cast<NSUInteger, size_t>(
requested_len.ValueOrDefault(0));
@@ -3013,6 +3097,9 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
[[NSString alloc] initWithBytes:bytes
length:bytes_len
encoding:NSUTF16LittleEndianStringEncoding]);
+ if (actualRange)
+ *actualRange = actual_range.ToNSRange();
+
return [[[NSAttributedString alloc] initWithString:ns_string] autorelease];
}
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 101493a8257..50dcc692cf5 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
@@ -317,6 +317,29 @@ TEST_F(RenderWidgetHostViewMacTest, AcceptsFirstResponder) {
EXPECT_TRUE([rwhv_cocoa_.get() acceptsFirstResponder]);
}
+// This test verifies that RenderWidgetHostViewCocoa's implementation of
+// NSTextInputClientConformance conforms to requirements.
+TEST_F(RenderWidgetHostViewMacTest, NSTextInputClientConformance) {
+ NSRange selectedRange = [rwhv_cocoa_ selectedRange];
+ EXPECT_EQ(0u, selectedRange.location);
+ EXPECT_EQ(0u, selectedRange.length);
+
+ NSRange actualRange = NSMakeRange(1u, 2u);
+ NSAttributedString* actualString = [rwhv_cocoa_
+ attributedSubstringForProposedRange:NSMakeRange(NSNotFound, 0u)
+ actualRange:&actualRange];
+ EXPECT_EQ(nil, actualString);
+ EXPECT_EQ(NSNotFound, actualRange.location);
+ EXPECT_EQ(0u, actualRange.length);
+
+ actualString = [rwhv_cocoa_
+ attributedSubstringForProposedRange:NSMakeRange(NSNotFound, 15u)
+ actualRange:&actualRange];
+ EXPECT_EQ(nil, actualString);
+ EXPECT_EQ(NSNotFound, actualRange.location);
+ EXPECT_EQ(0u, actualRange.length);
+}
+
TEST_F(RenderWidgetHostViewMacTest, Fullscreen) {
rwhv_mac_->InitAsFullscreen(NULL);
EXPECT_TRUE(rwhv_mac_->pepper_fullscreen_window());
@@ -903,6 +926,32 @@ TEST_F(RenderWidgetHostViewMacTest, LastWheelEventLatencyInfoExists) {
host->ShutdownAndDestroyWidget(true);
}
+TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
+ // Initialize the view associated with a MockRenderWidgetHostImpl, rather than
+ // the MockRenderProcessHost that is set up by the test harness which mocks
+ // out |OnMessageReceived()|.
+ TestBrowserContext browser_context;
+ MockRenderProcessHost* process_host =
+ new MockRenderProcessHost(&browser_context);
+ process_host->Init();
+ MockRenderWidgetHostDelegate delegate;
+ int32_t routing_id = process_host->GetNextRoutingID();
+ MockRenderWidgetHostImpl* host =
+ new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
+ process_host->sink().ClearMessages();
+
+ // Send a wheel event for scrolling by 3 lines.
+ // Verifies that SourceEventType exists in forwarded LatencyInfo object.
+ NSEvent* wheelEvent = MockScrollWheelEventWithPhase(@selector(phaseBegan), 3);
+ [view->cocoa_view() scrollWheel:wheelEvent];
+ ASSERT_TRUE(host->lastWheelEventLatencyInfo.source_event_type() ==
+ ui::SourceEventType::WHEEL);
+
+ // Clean up.
+ host->ShutdownAndDestroyWidget(true);
+}
+
TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
@@ -923,8 +972,13 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
[view->cocoa_view() scrollWheel:event1];
ASSERT_EQ(1U, process_host->sink().message_count());
+ // Flush and clear other messages (e.g. begin frames) the RWHVMac also sends.
+ base::RunLoop().RunUntilIdle();
+ process_host->sink().ClearMessages();
+
// Send an ACK for the first wheel event, so that the queue will be flushed.
- InputEventAck ack(blink::WebInputEvent::MouseWheel,
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
+ blink::WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
std::unique_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, ack));
@@ -935,7 +989,7 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[NSApp postEvent:event2 atStart:NO];
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(2U, process_host->sink().message_count());
+ ASSERT_EQ(1U, process_host->sink().message_count());
// Clean up.
host->ShutdownAndDestroyWidget(true);
@@ -969,7 +1023,8 @@ TEST_F(RenderWidgetHostViewMacTest,
process_host->sink().ClearMessages();
// Indicate that the wheel event was unhandled.
- InputEventAck unhandled_ack(blink::WebInputEvent::MouseWheel,
+ InputEventAck unhandled_ack(InputEventAckSource::COMPOSITOR_THREAD,
+ blink::WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
std::unique_ptr<IPC::Message> response1(
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
@@ -977,7 +1032,8 @@ TEST_F(RenderWidgetHostViewMacTest,
ASSERT_EQ(2U, process_host->sink().message_count());
process_host->sink().ClearMessages();
- InputEventAck unhandled_scroll_ack(blink::WebInputEvent::GestureScrollUpdate,
+ InputEventAck unhandled_scroll_ack(InputEventAckSource::COMPOSITOR_THREAD,
+ blink::WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
std::unique_ptr<IPC::Message> scroll_response1(
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_scroll_ack));
@@ -1138,7 +1194,8 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
process_host_->sink().ClearMessages();
// We'll use this IPC message to ack events.
- InputEventAck ack(blink::WebInputEvent::GesturePinchUpdate,
+ InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
+ blink::WebInputEvent::GesturePinchUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
std::unique_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, ack));
@@ -1463,4 +1520,95 @@ TEST_F(InputMethodMacTest, ImeCancelCompositionForAllViews) {
EXPECT_FALSE([rwhv_cocoa_ hasMarkedText]);
}
+// This test verifies that when a RenderWidgetHostView changes its
+// TextInputState to NONE we send the IPC to stop monitor composition info and,
+// conversely, when its state is set to non-NONE, we start monitoring the
+// composition info.
+TEST_F(InputMethodMacTest, MonitorCompositionRangeForActiveWidget) {
+ // First, we need to make the cocoa view the first responder so that the
+ // method RWHVMac::HasFocus() returns true. Then we can make sure that as long
+ // as there is some TextInputState of non-NONE, the corresponding widget will
+ // be asked to start monitoring composition info.
+ base::scoped_nsobject<CocoaTestHelperWindow> window(
+ [[CocoaTestHelperWindow alloc] init]);
+ [[window contentView] addSubview:rwhv_cocoa_];
+ [window makeFirstResponder:rwhv_cocoa_];
+ EXPECT_TRUE(rwhv_mac_->HasFocus());
+
+ TextInputState state;
+ state.type = ui::TEXT_INPUT_TYPE_TEXT;
+ tab_sink().ClearMessages();
+
+ // Make the tab's widget active.
+ rwhv_mac_->TextInputStateChanged(state);
+
+ // The tab's widget must have received an IPC regarding composition updates.
+ const IPC::Message* composition_request_msg_for_tab =
+ tab_sink().GetUniqueMessageMatching(
+ InputMsg_RequestCompositionUpdate::ID);
+ EXPECT_TRUE(composition_request_msg_for_tab);
+
+ // The message should ask for monitoring updates, but no immediate update.
+ InputMsg_RequestCompositionUpdate::Param tab_msg_params;
+ InputMsg_RequestCompositionUpdate::Read(composition_request_msg_for_tab,
+ &tab_msg_params);
+ bool is_tab_msg_for_immediate_request = std::get<0>(tab_msg_params);
+ bool is_tab_msg_for_monitor_request = std::get<1>(tab_msg_params);
+ EXPECT_FALSE(is_tab_msg_for_immediate_request);
+ EXPECT_TRUE(is_tab_msg_for_monitor_request);
+ tab_sink().ClearMessages();
+ child_sink().ClearMessages();
+
+ // Now make the child view active.
+ child_view_->TextInputStateChanged(state);
+
+ // The tab should receive another IPC for composition updates.
+ composition_request_msg_for_tab = tab_sink().GetUniqueMessageMatching(
+ InputMsg_RequestCompositionUpdate::ID);
+ EXPECT_TRUE(composition_request_msg_for_tab);
+
+ // This time, the tab should have been asked to stop monitoring (and no
+ // immediate updates).
+ InputMsg_RequestCompositionUpdate::Read(composition_request_msg_for_tab,
+ &tab_msg_params);
+ is_tab_msg_for_immediate_request = std::get<0>(tab_msg_params);
+ is_tab_msg_for_monitor_request = std::get<1>(tab_msg_params);
+ EXPECT_FALSE(is_tab_msg_for_immediate_request);
+ EXPECT_FALSE(is_tab_msg_for_monitor_request);
+ tab_sink().ClearMessages();
+
+ // The child too must have received an IPC for composition updates.
+ const IPC::Message* composition_request_msg_for_child =
+ child_sink().GetUniqueMessageMatching(
+ InputMsg_RequestCompositionUpdate::ID);
+ EXPECT_TRUE(composition_request_msg_for_child);
+
+ // Verify that the message is asking for monitoring to start; but no immediate
+ // updates.
+ InputMsg_RequestCompositionUpdate::Param child_msg_params;
+ InputMsg_RequestCompositionUpdate::Read(composition_request_msg_for_child,
+ &child_msg_params);
+ bool is_child_msg_for_immediate_request = std::get<0>(child_msg_params);
+ bool is_child_msg_for_monitor_request = std::get<1>(child_msg_params);
+ EXPECT_FALSE(is_child_msg_for_immediate_request);
+ EXPECT_TRUE(is_child_msg_for_monitor_request);
+ child_sink().ClearMessages();
+
+ // Make the tab view active again.
+ rwhv_mac_->TextInputStateChanged(state);
+
+ // Verify that the child received another IPC for composition updates.
+ composition_request_msg_for_child = child_sink().GetUniqueMessageMatching(
+ InputMsg_RequestCompositionUpdate::ID);
+ EXPECT_TRUE(composition_request_msg_for_child);
+
+ // Verify that this IPC is asking for no monitoring or immediate updates.
+ InputMsg_RequestCompositionUpdate::Read(composition_request_msg_for_child,
+ &child_msg_params);
+ is_child_msg_for_immediate_request = std::get<0>(child_msg_params);
+ is_child_msg_for_monitor_request = std::get<1>(child_msg_params);
+ EXPECT_FALSE(is_child_msg_for_immediate_request);
+ EXPECT_FALSE(is_child_msg_for_monitor_request);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc b/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
index bc51e9a2073..e6f006f5ff1 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -12,7 +12,7 @@
#include "content/common/render_widget_window_tree_client_factory.mojom.h"
#include "content/common/text_input_state.h"
#include "content/public/common/service_manager_connection.h"
-#include "services/shell/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/public/cpp/property_type_converters.h"
#include "services/ui/public/cpp/window.h"
#include "services/ui/public/cpp/window_property.h"
@@ -186,11 +186,11 @@ void RenderWidgetHostViewMus::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewMus::TextInputStateChanged(
const TextInputState& params) {
- // TODO(fsamuel): Implement an IME mojo app.
+ // TODO(fsamuel): Implement an IME service.
}
void RenderWidgetHostViewMus::ImeCancelComposition() {
- // TODO(fsamuel): Implement an IME mojo app.
+ // TODO(fsamuel): Implement an IME service.
}
void RenderWidgetHostViewMus::ImeCompositionRangeChanged(
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mus.h b/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
index cb1e2a42010..ea2280c6aa1 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
@@ -19,14 +19,13 @@ namespace content {
class RenderWidgetHost;
class RenderWidgetHostImpl;
-struct NativeWebKeyboardEvent;
struct TextInputState;
// See comments in render_widget_host_view.h about this class and its members.
// This version of RenderWidgetHostView is for builds of Chrome that run through
-// the mojo shell and use the Mandoline UI Service (Mus). Mus is responsible for
-// windowing, compositing, and input event dispatch. The purpose of
-// RenderWidgetHostViewMus is to manage the ui::Window owned by the content
+// the standalone service runner and use the Mandoline UI Service (Mus). Mus is
+// responsible for windowing, compositing, and input event dispatch. The purpose
+// of RenderWidgetHostViewMus is to manage the ui::Window owned by the content
// embedder. The browser is the owner of the ui::Window, controlling properties
// such as visibility, and bounds. Some aspects such as input, focus, and cursor
// are managed by Mus directly. Input event routing will be plumbed directly to
diff --git a/chromium/content/browser/renderer_host/renderer_frame_manager.cc b/chromium/content/browser/renderer_host/renderer_frame_manager.cc
index 1eff47d67da..a05a92c3f59 100644
--- a/chromium/content/browser/renderer_host/renderer_frame_manager.cc
+++ b/chromium/content/browser/renderer_host/renderer_frame_manager.cc
@@ -8,12 +8,15 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/memory_coordinator_client_registry.h"
+#include "base/memory/memory_coordinator_proxy.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/shared_memory.h"
#include "base/sys_info.h"
#include "build/build_config.h"
#include "content/common/host_shared_bitmap_manager.h"
+#include "content/public/common/content_features.h"
namespace content {
namespace {
@@ -72,35 +75,50 @@ void RendererFrameManager::UnlockFrame(RendererFrameManagerClient* frame) {
}
size_t RendererFrameManager::GetMaxNumberOfSavedFrames() const {
- base::MemoryPressureMonitor* monitor = base::MemoryPressureMonitor::Get();
-
- if (!monitor)
- return max_number_of_saved_frames_;
-
- // Until we have a global OnMemoryPressureChanged event we need to query the
- // value from our specific pressure monitor.
int percentage = 100;
- switch (monitor->GetCurrentPressureLevel()) {
- case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
- percentage = 100;
- break;
- case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
- percentage = kModeratePressurePercentage;
- break;
- case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
- percentage = kCriticalPressurePercentage;
- break;
+ if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
+ switch (base::MemoryCoordinatorProxy::GetInstance()->
+ GetCurrentMemoryState()) {
+ case base::MemoryState::NORMAL:
+ percentage = 100;
+ break;
+ case base::MemoryState::THROTTLED:
+ percentage = kCriticalPressurePercentage;
+ break;
+ case base::MemoryState::SUSPENDED:
+ case base::MemoryState::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+ } else {
+ base::MemoryPressureMonitor* monitor = base::MemoryPressureMonitor::Get();
+
+ if (!monitor)
+ return max_number_of_saved_frames_;
+
+ // Until we have a global OnMemoryPressureChanged event we need to query the
+ // value from our specific pressure monitor.
+ switch (monitor->GetCurrentPressureLevel()) {
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+ percentage = 100;
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ percentage = kModeratePressurePercentage;
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ percentage = kCriticalPressurePercentage;
+ break;
+ }
}
size_t frames = (max_number_of_saved_frames_ * percentage) / 100;
return std::max(static_cast<size_t>(1), frames);
}
RendererFrameManager::RendererFrameManager()
- : memory_pressure_listener_(
+ : memory_pressure_listener_(new base::MemoryPressureListener(
base::Bind(&RendererFrameManager::OnMemoryPressure,
- base::Unretained(this))) {
- // Note: With the destruction of this class the |memory_pressure_listener_|
- // gets destroyed and the observer will remove itself.
+ base::Unretained(this)))) {
+ base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
max_number_of_saved_frames_ =
#if defined(OS_ANDROID)
// If the amount of memory on the device is >= 3.5 GB, save up to 5
@@ -136,21 +154,40 @@ void RendererFrameManager::CullUnlockedFrames(size_t saved_frame_limit) {
void RendererFrameManager::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
- int saved_frame_limit = max_number_of_saved_frames_;
- if (saved_frame_limit <= 1)
- return;
- int percentage = 100;
switch (memory_pressure_level) {
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
- percentage = kModeratePressurePercentage;
+ PurgeMemory(kModeratePressurePercentage);
break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
- percentage = kCriticalPressurePercentage;
+ PurgeMemory(kCriticalPressurePercentage);
break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
// No need to change anything when there is no pressure.
return;
}
+}
+
+void RendererFrameManager::OnMemoryStateChange(base::MemoryState state) {
+ switch (state) {
+ case base::MemoryState::NORMAL:
+ // It is not necessary to purge here.
+ break;
+ case base::MemoryState::THROTTLED:
+ PurgeMemory(kCriticalPressurePercentage);
+ break;
+ case base::MemoryState::SUSPENDED:
+ // Note that SUSPENDED never occurs in the main browser process so far.
+ // Fall through.
+ case base::MemoryState::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+}
+
+void RendererFrameManager::PurgeMemory(int percentage) {
+ int saved_frame_limit = max_number_of_saved_frames_;
+ if (saved_frame_limit <= 1)
+ return;
CullUnlockedFrames(std::max(1, (saved_frame_limit * percentage) / 100));
}
diff --git a/chromium/content/browser/renderer_host/renderer_frame_manager.h b/chromium/content/browser/renderer_host/renderer_frame_manager.h
index 87385481f2e..061be97e3cf 100644
--- a/chromium/content/browser/renderer_host/renderer_frame_manager.h
+++ b/chromium/content/browser/renderer_host/renderer_frame_manager.h
@@ -11,6 +11,7 @@
#include <map>
#include "base/macros.h"
+#include "base/memory/memory_coordinator_client.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
@@ -31,7 +32,8 @@ class CONTENT_EXPORT RendererFrameManagerClient {
// between a small set of tabs faster. The limit is a soft limit, because
// clients can lock their frame to prevent it from being discarded, e.g. if the
// tab is visible, or while capturing a screenshot.
-class CONTENT_EXPORT RendererFrameManager {
+class CONTENT_EXPORT RendererFrameManager :
+ public base::MemoryCoordinatorClient {
public:
static RendererFrameManager* GetInstance();
@@ -53,18 +55,24 @@ class CONTENT_EXPORT RendererFrameManager {
friend class RenderWidgetHostViewAuraTest;
RendererFrameManager();
- ~RendererFrameManager();
+ ~RendererFrameManager() override;
+
+ // base::MemoryCoordinatorClient implementation:
+ void OnMemoryStateChange(base::MemoryState state) override;
+
void CullUnlockedFrames(size_t saved_frame_limit);
// React on memory pressure events to adjust the number of cached frames.
void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+ void PurgeMemory(int percentage);
+
friend struct base::DefaultSingletonTraits<RendererFrameManager>;
// Listens for system under pressure notifications and adjusts number of
// cached frames accordingly.
- base::MemoryPressureListener memory_pressure_listener_;
+ std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
std::map<RendererFrameManagerClient*, size_t> locked_frames_;
std::list<RendererFrameManagerClient*> unlocked_frames_;
diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc
index 3c15100c444..3b75d36aca9 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.cc
+++ b/chromium/content/browser/renderer_host/text_input_manager.cc
@@ -140,8 +140,8 @@ void TextInputManager::UpdateTextInputState(
void TextInputManager::ImeCancelComposition(RenderWidgetHostViewBase* view) {
DCHECK(IsRegistered(view));
- FOR_EACH_OBSERVER(Observer, observer_list_,
- OnImeCancelComposition(this, view));
+ for (auto& observer : observer_list_)
+ observer.OnImeCancelComposition(this, view);
}
void TextInputManager::SelectionBoundsChanged(
@@ -203,8 +203,8 @@ void TextInputManager::SelectionBoundsChanged(
selection_region_map_[view].first_selection_rect.set_size(
params.anchor_rect.size());
- FOR_EACH_OBSERVER(Observer, observer_list_,
- OnSelectionBoundsChanged(this, view));
+ for (auto& observer : observer_list_)
+ observer.OnSelectionBoundsChanged(this, view);
}
// TODO(ekaramad): We use |range| only on Mac OS; but we still track its value
@@ -227,8 +227,8 @@ void TextInputManager::ImeCompositionRangeChanged(
composition_range_info_map_[view].range.set_start(range.start());
composition_range_info_map_[view].range.set_end(range.end());
- FOR_EACH_OBSERVER(Observer, observer_list_,
- OnImeCompositionRangeChanged(this, view));
+ for (auto& observer : observer_list_)
+ observer.OnImeCompositionRangeChanged(this, view);
}
void TextInputManager::SelectionChanged(RenderWidgetHostViewBase* view,
@@ -242,8 +242,8 @@ void TextInputManager::SelectionChanged(RenderWidgetHostViewBase* view,
text_selection_map_[view].range.set_start(range.start());
text_selection_map_[view].range.set_end(range.end());
- FOR_EACH_OBSERVER(Observer, observer_list_,
- OnTextSelectionChanged(this, view));
+ for (auto& observer : observer_list_)
+ observer.OnTextSelectionChanged(this, view);
}
void TextInputManager::Register(RenderWidgetHostViewBase* view) {
@@ -299,9 +299,8 @@ ui::TextInputType TextInputManager::GetTextInputTypeForViewForTesting(
void TextInputManager::NotifyObserversAboutInputStateUpdate(
RenderWidgetHostViewBase* updated_view,
bool did_update_state) {
- FOR_EACH_OBSERVER(
- Observer, observer_list_,
- OnUpdateTextInputStateCalled(this, updated_view, did_update_state));
+ for (auto& observer : observer_list_)
+ observer.OnUpdateTextInputStateCalled(this, updated_view, did_update_state);
}
TextInputManager::SelectionRegion::SelectionRegion() {}
diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h
index 4bf2da6b7c2..db2383bd9b1 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.h
+++ b/chromium/content/browser/renderer_host/text_input_manager.h
@@ -23,7 +23,6 @@ namespace content {
class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
-class WebContents;
// A class which receives updates of TextInputState from multiple sources and
// decides what the new TextInputState is. It also notifies the observers when
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 38c2b28b051..01fbe154abe 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -7,7 +7,7 @@
#include <stdint.h>
#include "content/common/input/web_touch_event_traits.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index 1a196086837..1afc709404d 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -7,8 +7,8 @@
#include <tuple>
#include "base/memory/ptr_util.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/common/view_messages.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
#include "net/base/net_errors.h"
#include "net/proxy/mock_proxy_resolver.h"
@@ -66,8 +66,7 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
new net::ProxyService(base::WrapUnique(new MockProxyConfigService),
base::WrapUnique(resolver_factory_),
NULL)),
- helper_(new TestResolveProxyMsgHelper(service_.get(), this)),
- io_thread_(BrowserThread::IO, &message_loop_) {
+ helper_(new TestResolveProxyMsgHelper(service_.get(), this)) {
test_sink_.AddFilter(this);
}
@@ -102,8 +101,7 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
return true;
}
- base::MessageLoopForIO message_loop_;
- BrowserThreadImpl io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
IPC::TestSink test_sink_;
};
@@ -128,10 +126,10 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
net::OK, &resolver_);
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url1, resolver_.pending_requests()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result1:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result1:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -140,10 +138,10 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
helper_->OnResolveProxy(url2, msg2);
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url2, resolver_.pending_requests()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result2:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url2, resolver_.pending_jobs()[0]->url());
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result2:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -152,10 +150,10 @@ TEST_F(ResolveProxyMsgHelperTest, Sequential) {
helper_->OnResolveProxy(url3, msg3);
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url3, resolver_.pending_requests()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result3:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url3, resolver_.pending_jobs()[0]->url());
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result3:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -188,33 +186,33 @@ TEST_F(ResolveProxyMsgHelperTest, QueueRequests) {
// ResolveProxyHelper only keeps 1 request outstanding in ProxyService
// at a time.
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url1, resolver_.pending_requests()[0]->url());
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result1:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result1:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list);
clear_pending_result();
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url2, resolver_.pending_requests()[0]->url());
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url2, resolver_.pending_jobs()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result2:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result2:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list);
clear_pending_result();
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url3, resolver_.pending_requests()[0]->url());
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url3, resolver_.pending_jobs()[0]->url());
- resolver_.pending_requests()[0]->results()->UseNamedProxy("result3:80");
- resolver_.pending_requests()[0]->CompleteNow(net::OK);
+ resolver_.pending_jobs()[0]->results()->UseNamedProxy("result3:80");
+ resolver_.pending_jobs()[0]->CompleteNow(net::OK);
// Check result.
EXPECT_EQ(true, pending_result()->result);
@@ -248,8 +246,8 @@ TEST_F(ResolveProxyMsgHelperTest, CancelPendingRequests) {
// ResolveProxyHelper only keeps 1 request outstanding in ProxyService
// at a time.
- ASSERT_EQ(1u, resolver_.pending_requests().size());
- EXPECT_EQ(url1, resolver_.pending_requests()[0]->url());
+ ASSERT_EQ(1u, resolver_.pending_jobs().size());
+ EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
// Delete the underlying ResolveProxyMsgHelper -- this should cancel all
// the requests which are outstanding.
@@ -257,7 +255,7 @@ TEST_F(ResolveProxyMsgHelperTest, CancelPendingRequests) {
// The pending requests sent to the proxy resolver should have been cancelled.
- EXPECT_EQ(0u, resolver_.pending_requests().size());
+ EXPECT_EQ(0u, resolver_.pending_jobs().size());
EXPECT_TRUE(pending_result() == NULL);
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index f2ef8435e7e..bcd24f896c0 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -96,6 +96,7 @@ cr.define('gpu', function() {
'multiple_raster_threads': 'Multiple Raster Threads',
'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
'vpx_decode': 'VPx Video Decode',
+ 'webgl2': 'WebGL2',
};
var statusMap = {
diff --git a/chromium/content/browser/resources/media/cache_entry.js b/chromium/content/browser/resources/media/cache_entry.js
index e4b3f0d3e05..2286fe03d62 100644
--- a/chromium/content/browser/resources/media/cache_entry.js
+++ b/chromium/content/browser/resources/media/cache_entry.js
@@ -200,7 +200,7 @@ cr.define('media', function() {
var footerRow = document.createElement('tr');
var footerCell = document.createElement('td');
- footerCell.textContent = 'Out of ' + (this.size || 'unkown size');
+ footerCell.textContent = 'Out of ' + (this.size || 'unknown size');
footerCell.setAttribute('colspan', 2);
footerRow.appendChild(footerCell);
footer.appendChild(footerRow);
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index ccee09ee122..63c7dcf660e 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -13,6 +13,7 @@ var ClientRenderer = (function() {
this.graphElement = document.getElementById('graphs');
this.audioPropertyName = document.getElementById('audio-property-name');
+ this.players = null;
this.selectedPlayer = null;
this.selectedAudioComponentType = null;
this.selectedAudioComponentId = null;
@@ -34,6 +35,9 @@ var ClientRenderer = (function() {
clipboardButtons[i].onclick = this.copyToClipboard_.bind(this);
}
+ this.saveLogButton = document.getElementById('save-log-button');
+ this.saveLogButton.onclick = this.saveLog_.bind(this);
+
this.hiddenKeys = ['component_id', 'component_type', 'owner_id'];
// Tell CSS to hide certain content prior to making selections.
@@ -93,6 +97,14 @@ var ClientRenderer = (function() {
element.checked = true;
}
+ function downloadLog(text) {
+ var file = new Blob([text], {type: 'text/plain'});
+ var a = document.createElement('a');
+ a.href = URL.createObjectURL(file);
+ a.download = "media-internals.txt";
+ a.click();
+ }
+
ClientRenderer.prototype = {
/**
* Called when an audio component is added to the collection.
@@ -230,7 +242,7 @@ var ClientRenderer = (function() {
}
},
- getAudioComponentName_ : function(componentType, id) {
+ getAudioComponentName_: function(componentType, id) {
var baseName;
switch (componentType) {
case 0:
@@ -248,7 +260,7 @@ var ClientRenderer = (function() {
return baseName + ' ' + id;
},
- getListElementForAudioComponent_ : function(componentType) {
+ getListElementForAudioComponent_: function(componentType) {
var listElement;
switch (componentType) {
case 0:
@@ -304,8 +316,7 @@ var ClientRenderer = (function() {
}
},
- selectAudioComponent_: function(
- componentType, componentId, componentData) {
+ selectAudioComponent_: function(componentType, componentId, componentData) {
document.body.classList.remove(
ClientRenderer.Css_.NO_COMPONENTS_SELECTED);
@@ -320,12 +331,16 @@ var ClientRenderer = (function() {
},
redrawPlayerList_: function(players) {
+ this.players = players;
+
// Group name imposes rule that only one component can be selected
// (and have its properties displayed) at a time.
var buttonGroupName = 'player-buttons';
+ var hasPlayers = false;
var fragment = document.createDocumentFragment();
for (id in players) {
+ hasPlayers = true;
var player = players[id];
var usableName = player.properties.name ||
player.properties.url ||
@@ -344,6 +359,8 @@ var ClientRenderer = (function() {
// Re-select the selected player since the button was just recreated.
selectSelectableButton(this.selectedPlayer.id);
}
+
+ this.saveLogButton.style.display = hasPlayers ? "inline-block" : "none";
},
selectPlayer_: function(player) {
@@ -400,6 +417,15 @@ var ClientRenderer = (function() {
this.selectedPlayerLogIndex = this.selectedPlayer.allEvents.length;
},
+ saveLog_: function() {
+ var strippedPlayers = []
+ for (id in this.players) {
+ var p = this.players[id];
+ strippedPlayers.push({properties: p.properties, events: p.allEvents});
+ }
+ downloadLog(JSON.stringify(strippedPlayers, null, 2));
+ },
+
drawGraphs_: function() {
function addToGraphs(name, graph, graphElement) {
var li = document.createElement('li');
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index be0d684cc00..8782a4c496c 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -27,6 +27,7 @@ found in the LICENSE file.
</tabs>
<tabpanels>
<tabpanel id="players">
+ <button id="save-log-button" style="display:none">Save log</button>
<div id="list-wrapper">
<div id="player-list-wrapper">
<h2>Recent Players</h2>
diff --git a/chromium/content/browser/resources/media/player_info.js b/chromium/content/browser/resources/media/player_info.js
index af1f1944518..3fad95d838e 100644
--- a/chromium/content/browser/resources/media/player_info.js
+++ b/chromium/content/browser/resources/media/player_info.js
@@ -17,8 +17,6 @@ var PlayerInfo = (function() {
this.id = id;
// The current value of the properties for this player.
this.properties = {};
- // All of the past (and present) values of the properties.
- this.pastValues = {};
// Every single event in the order in which they were received.
this.allEvents = [];
@@ -48,17 +46,12 @@ var PlayerInfo = (function() {
this.properties[key] = value;
- if (!this.pastValues[key]) {
- this.pastValues[key] = [];
- }
-
var recordValue = {
time: timestamp - this.firstTimestamp_,
key: key,
value: value
};
- this.pastValues[key].push(recordValue);
this.allEvents.push(recordValue);
},
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
index 540fc43360a..aeb3d4da1f6 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -55,8 +55,7 @@ class ScreenOrientationBrowserTest : public ContentBrowserTest {
params.new_size = gfx::Size(0, 0);
params.physical_backing_size = gfx::Size(300, 300);
params.top_controls_height = 0.f;
- params.top_controls_shrink_blink_size = false;
- params.resizer_rect = gfx::Rect();
+ params.browser_controls_shrink_blink_size = false;
params.is_fullscreen_granted = false;
rwh->Send(new ViewMsg_Resize(rwh->GetRoutingID(), params));
}
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
index a2b6977b5bd..6a0dec1458e 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
@@ -6,6 +6,8 @@
#include "content/browser/android/content_view_core_impl.h"
#include "jni/ScreenOrientationProvider_jni.h"
+#include "ui/android/window_android.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -39,8 +41,11 @@ bool ScreenOrientationDelegateAndroid::FullScreenRequired(
void ScreenOrientationDelegateAndroid::Lock(
WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) {
+ gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProvider_lockOrientation(
- base::android::AttachCurrentThread(), lock_orientation);
+ base::android::AttachCurrentThread(),
+ window ? window->GetJavaObject() : nullptr,
+ lock_orientation);
}
bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
@@ -49,8 +54,10 @@ bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
}
void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) {
+ gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProvider_unlockOrientation(
- base::android::AttachCurrentThread());
+ base::android::AttachCurrentThread(),
+ window ? window->GetJavaObject() : nullptr);
}
} // namespace content
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 8b5c4cc1582..53622ac0df4 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -91,8 +91,8 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
wc->GetFrameTree()->root()->navigator()->RequestOpenURL(
wc->GetFrameTree()->root()->current_frame_host(), extension_url, false,
- nullptr, nullptr, Referrer(), WindowOpenDisposition::CURRENT_TAB, false,
- true);
+ nullptr, std::string(), Referrer(), WindowOpenDisposition::CURRENT_TAB,
+ false, true);
// Since the navigation above requires a cross-process swap, there will be a
// speculative/pending RenderFrameHost. Ensure it exists and is in a different
@@ -115,6 +115,7 @@ ResourceRequest CreateXHRRequest(const char* url) {
request.method = "GET";
request.url = GURL(url);
request.referrer_policy = blink::WebReferrerPolicyDefault;
+ request.request_initiator = url::Origin();
request.load_flags = 0;
request.origin_pid = 0;
request.resource_type = RESOURCE_TYPE_XHR;
@@ -530,7 +531,6 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MismatchedOriginOnCommit) {
// Create commit params with different origins in params.url and
// params.origin.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.page_id = 0;
params.nav_entry_id = 0;
params.did_create_new_entry = false;
params.url = url;
diff --git a/chromium/content/browser/service_manager/OWNERS b/chromium/content/browser/service_manager/OWNERS
index 25fd31a3c4d..041852810f7 100644
--- a/chromium/content/browser/service_manager/OWNERS
+++ b/chromium/content/browser/service_manager/OWNERS
@@ -1 +1,2 @@
+ben@chromium.org
rockot@chromium.org
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index d35d069dc13..2b211b4511f 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -24,33 +24,35 @@
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/service_manager_connection.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "mojo/edk/embedder/embedder.h"
#include "services/catalog/catalog.h"
#include "services/catalog/manifest_provider.h"
+#include "services/catalog/public/interfaces/constants.mojom.h"
#include "services/catalog/store.h"
-#include "services/file/public/cpp/constants.h"
-#include "services/shell/connect_params.h"
-#include "services/shell/native_runner.h"
-#include "services/shell/public/cpp/connector.h"
-#include "services/shell/public/cpp/service.h"
-#include "services/shell/public/interfaces/service.mojom.h"
-#include "services/shell/runner/common/client_util.h"
-#include "services/shell/runner/host/in_process_native_runner.h"
-#include "services/shell/service_manager.h"
+#include "services/file/public/interfaces/constants.mojom.h"
+#include "services/service_manager/connect_params.h"
+#include "services/service_manager/native_runner.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/interfaces/service.mojom.h"
+#include "services/service_manager/runner/common/client_util.h"
+#include "services/service_manager/runner/host/in_process_native_runner.h"
+#include "services/service_manager/service_manager.h"
namespace content {
namespace {
-base::LazyInstance<std::unique_ptr<shell::Connector>>::Leaky
+base::LazyInstance<std::unique_ptr<service_manager::Connector>>::Leaky
g_io_thread_connector = LAZY_INSTANCE_INITIALIZER;
void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); }
-void StartUtilityProcessOnIOThread(shell::mojom::ServiceFactoryRequest request,
- const base::string16& process_name,
- bool use_sandbox) {
+void StartUtilityProcessOnIOThread(
+ service_manager::mojom::ServiceFactoryRequest request,
+ const base::string16& process_name,
+ bool use_sandbox) {
UtilityProcessHost* process_host =
UtilityProcessHost::Create(nullptr, nullptr);
process_host->SetName(process_name);
@@ -60,11 +62,12 @@ void StartUtilityProcessOnIOThread(shell::mojom::ServiceFactoryRequest request,
process_host->GetRemoteInterfaces()->GetInterface(std::move(request));
}
-void StartServiceInUtilityProcess(const std::string& service_name,
- const base::string16& process_name,
- bool use_sandbox,
- shell::mojom::ServiceRequest request) {
- shell::mojom::ServiceFactoryPtr service_factory;
+void StartServiceInUtilityProcess(
+ const std::string& service_name,
+ const base::string16& process_name,
+ bool use_sandbox,
+ service_manager::mojom::ServiceRequest request) {
+ service_manager::mojom::ServiceFactoryPtr service_factory;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&StartUtilityProcessOnIOThread,
base::Passed(GetProxy(&service_factory)),
@@ -74,9 +77,11 @@ void StartServiceInUtilityProcess(const std::string& service_name,
#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-// Request shell::mojom::ServiceFactory from GPU process host. Must be called on
+// Request service_manager::mojom::ServiceFactory from GPU process host. Must be
+// called on
// IO thread.
-void RequestGpuServiceFactory(shell::mojom::ServiceFactoryRequest request) {
+void RequestGpuServiceFactory(
+ service_manager::mojom::ServiceFactoryRequest request) {
GpuProcessHost* process_host =
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED);
if (!process_host) {
@@ -92,8 +97,8 @@ void RequestGpuServiceFactory(shell::mojom::ServiceFactoryRequest request) {
}
void StartServiceInGpuProcess(const std::string& service_name,
- shell::mojom::ServiceRequest request) {
- shell::mojom::ServiceFactoryPtr service_factory;
+ service_manager::mojom::ServiceRequest request) {
+ service_manager::mojom::ServiceFactoryPtr service_factory;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&RequestGpuServiceFactory,
@@ -137,12 +142,12 @@ class ServiceManagerContext::InProcessServiceManagerContext
public:
InProcessServiceManagerContext() {}
- shell::mojom::ServiceRequest Start(
+ service_manager::mojom::ServiceRequest Start(
std::unique_ptr<BuiltinManifestProvider> manifest_provider) {
- shell::mojom::ServicePtr embedder_service_proxy;
- shell::mojom::ServiceRequest embedder_service_request =
+ service_manager::mojom::ServicePtr embedder_service_proxy;
+ service_manager::mojom::ServiceRequest embedder_service_request =
mojo::GetProxy(&embedder_service_proxy);
- shell::mojom::ServicePtrInfo embedder_service_proxy_info =
+ service_manager::mojom::ServicePtrInfo embedder_service_proxy_info =
embedder_service_proxy.PassInterface();
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)->PostTask(
FROM_HERE,
@@ -165,19 +170,19 @@ class ServiceManagerContext::InProcessServiceManagerContext
void StartOnIOThread(
std::unique_ptr<BuiltinManifestProvider> manifest_provider,
- shell::mojom::ServicePtrInfo embedder_service_proxy_info) {
+ service_manager::mojom::ServicePtrInfo embedder_service_proxy_info) {
manifest_provider_ = std::move(manifest_provider);
base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
- std::unique_ptr<shell::NativeRunnerFactory> native_runner_factory(
- new shell::InProcessNativeRunnerFactory(blocking_pool));
+ std::unique_ptr<service_manager::NativeRunnerFactory> native_runner_factory(
+ new service_manager::InProcessNativeRunnerFactory(blocking_pool));
catalog_.reset(
new catalog::Catalog(blocking_pool, nullptr, manifest_provider_.get()));
- service_manager_.reset(new shell::ServiceManager(
+ service_manager_.reset(new service_manager::ServiceManager(
std::move(native_runner_factory), catalog_->TakeService()));
- shell::mojom::ServiceRequest request =
- service_manager_->StartEmbedderService(kBrowserServiceName);
+ service_manager::mojom::ServiceRequest request =
+ service_manager_->StartEmbedderService(mojom::kBrowserServiceName);
mojo::FuseInterface(
std::move(request), std::move(embedder_service_proxy_info));
}
@@ -190,16 +195,16 @@ class ServiceManagerContext::InProcessServiceManagerContext
std::unique_ptr<BuiltinManifestProvider> manifest_provider_;
std::unique_ptr<catalog::Catalog> catalog_;
- std::unique_ptr<shell::ServiceManager> service_manager_;
+ std::unique_ptr<service_manager::ServiceManager> service_manager_;
DISALLOW_COPY_AND_ASSIGN(InProcessServiceManagerContext);
};
ServiceManagerContext::ServiceManagerContext() {
- shell::mojom::ServiceRequest request;
- if (shell::ShellIsRemote()) {
+ service_manager::mojom::ServiceRequest request;
+ if (service_manager::ServiceManagerIsRemote()) {
mojo::edk::SetParentPipeHandleFromCommandLine();
- request = shell::GetServiceRequestFromCommandLine();
+ request = service_manager::GetServiceRequestFromCommandLine();
} else {
std::unique_ptr<BuiltinManifestProvider> manifest_provider =
base::MakeUnique<BuiltinManifestProvider>();
@@ -208,22 +213,27 @@ ServiceManagerContext::ServiceManagerContext() {
const char* name;
int resource_id;
} kManifests[] = {
- { kBrowserServiceName, IDR_MOJO_CONTENT_BROWSER_MANIFEST },
- { kGpuServiceName, IDR_MOJO_CONTENT_GPU_MANIFEST },
- { kPluginServiceName, IDR_MOJO_CONTENT_PLUGIN_MANIFEST },
- { kRendererServiceName, IDR_MOJO_CONTENT_RENDERER_MANIFEST },
- { kUtilityServiceName, IDR_MOJO_CONTENT_UTILITY_MANIFEST },
- { "service:catalog", IDR_MOJO_CATALOG_MANIFEST },
- { file::kFileServiceName, IDR_MOJO_FILE_MANIFEST }
+ { mojom::kBrowserServiceName, IDR_MOJO_CONTENT_BROWSER_MANIFEST },
+ { mojom::kGpuServiceName, IDR_MOJO_CONTENT_GPU_MANIFEST },
+ { mojom::kPluginServiceName, IDR_MOJO_CONTENT_PLUGIN_MANIFEST },
+ { mojom::kRendererServiceName, IDR_MOJO_CONTENT_RENDERER_MANIFEST },
+ { mojom::kUtilityServiceName, IDR_MOJO_CONTENT_UTILITY_MANIFEST },
+ { catalog::mojom::kServiceName, IDR_MOJO_CATALOG_MANIFEST },
+ { file::mojom::kServiceName, IDR_MOJO_FILE_MANIFEST }
};
for (size_t i = 0; i < arraysize(kManifests); ++i) {
std::string contents = GetContentClient()->GetDataResource(
kManifests[i].resource_id,
ui::ScaleFactor::SCALE_FACTOR_NONE).as_string();
- DCHECK(!contents.empty());
+ base::debug::Alias(&i);
+ CHECK(!contents.empty());
+
std::unique_ptr<base::Value> manifest_value =
base::JSONReader::Read(contents);
+ base::debug::Alias(&contents);
+ CHECK(manifest_value);
+
std::unique_ptr<base::Value> overlay_value =
GetContentClient()->browser()->GetServiceManifestOverlay(
kManifests[i].name);
@@ -234,6 +244,7 @@ ServiceManagerContext::ServiceManagerContext() {
CHECK(overlay_value->GetAsDictionary(&overlay_dictionary));
MergeDictionary(manifest_dictionary, overlay_dictionary);
}
+
manifest_provider->AddManifestValue(kManifests[i].name,
std::move(manifest_value));
}
@@ -283,7 +294,7 @@ ServiceManagerContext::ServiceManagerContext() {
#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
ServiceManagerConnection::GetForProcess()->AddServiceRequestHandler(
- "service:media", base::Bind(&StartServiceInGpuProcess, "service:media"));
+ "media", base::Bind(&StartServiceInGpuProcess, "media"));
#endif
}
@@ -301,7 +312,7 @@ ServiceManagerContext::~ServiceManagerContext() {
}
// static
-shell::Connector* ServiceManagerContext::GetConnectorForIOThread() {
+service_manager::Connector* ServiceManagerContext::GetConnectorForIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return g_io_thread_connector.Get().get();
}
diff --git a/chromium/content/browser/service_manager/service_manager_context.h b/chromium/content/browser/service_manager/service_manager_context.h
index 273ead7f69b..d2c025c12b4 100644
--- a/chromium/content/browser/service_manager/service_manager_context.h
+++ b/chromium/content/browser/service_manager/service_manager_context.h
@@ -9,7 +9,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-namespace shell {
+namespace service_manager {
class Connector;
}
@@ -23,8 +23,8 @@ class CONTENT_EXPORT ServiceManagerContext {
ServiceManagerContext();
~ServiceManagerContext();
- // Returns a shell::Connector that can be used on the IO thread.
- static shell::Connector* GetConnectorForIOThread();
+ // Returns a service_manager::Connector that can be used on the IO thread.
+ static service_manager::Connector* GetConnectorForIOThread();
private:
class InProcessServiceManagerContext;
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 17d4cd49e02..6fb30fdeff7 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -29,8 +29,8 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#include "url/gurl.h"
namespace content {
@@ -108,8 +108,8 @@ void SetupOnUI(
void SetupMojoOnUIThread(
int process_id,
int thread_id,
- shell::mojom::InterfaceProviderRequest remote_interfaces,
- shell::mojom::InterfaceProviderPtrInfo exposed_interfaces) {
+ service_manager::mojom::InterfaceProviderRequest remote_interfaces,
+ service_manager::mojom::InterfaceProviderPtrInfo exposed_interfaces) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
// |rph| or its InterfaceProvider may be NULL in unit tests.
if (!rph || !rph->GetRemoteInterfaces())
@@ -121,6 +121,17 @@ void SetupMojoOnUIThread(
mojo::MakeProxy(std::move(exposed_interfaces)));
}
+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)) {
+ DCHECK(ServiceWorkerUtils::IsMojoForServiceWorkerEnabled());
+ return;
+ }
+ instance->Detach();
+}
+
} // namespace
// Lives on IO thread, proxies notifications to DevToolsManager that lives on
@@ -375,7 +386,7 @@ class EmbeddedWorkerInstance::StartTask {
params->wait_for_debugger = wait_for_debugger;
if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled())
- instance_->SendMojoStartWorker(std::move(params));
+ SendMojoStartWorker(std::move(params));
else
SendStartWorker(std::move(params));
}
@@ -400,6 +411,18 @@ class EmbeddedWorkerInstance::StartTask {
// is evaluated.
}
+ void SendMojoStartWorker(std::unique_ptr<EmbeddedWorkerStartParams> params) {
+ ServiceWorkerStatusCode status =
+ instance_->SendMojoStartWorker(std::move(params));
+ if (status != SERVICE_WORKER_OK) {
+ StatusCallback callback = start_callback_;
+ start_callback_.Reset();
+ instance_->OnStartFailed(callback, status);
+ // |this| may be destroyed.
+ return;
+ }
+ }
+
// |instance_| must outlive |this|.
EmbeddedWorkerInstance* instance_;
@@ -450,9 +473,11 @@ void EmbeddedWorkerInstance::Start(
status_ = EmbeddedWorkerStatus::STARTING;
starting_phase_ = ALLOCATING_PROCESS;
network_accessed_for_script_ = false;
- interface_registry_.reset(new shell::InterfaceRegistry);
- remote_interfaces_.reset(new shell::InterfaceProvider);
- FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting());
+ interface_registry_ =
+ base::MakeUnique<service_manager::InterfaceRegistry>(std::string());
+ remote_interfaces_.reset(new service_manager::InterfaceProvider);
+ for (auto& observer : listener_list_)
+ observer.OnStarting();
params->embedded_worker_id = embedded_worker_id_;
params->worker_devtools_agent_route_id = MSG_ROUTING_NONE;
@@ -460,8 +485,11 @@ void EmbeddedWorkerInstance::Start(
params->settings.v8_cache_options = GetV8CacheOptions();
mojom::EmbeddedWorkerInstanceClientRequest request;
- if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled())
+ if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) {
request = mojo::GetProxy(&client_);
+ client_.set_connection_error_handler(
+ base::Bind(&CallDetach, base::Unretained(this)));
+ }
inflight_start_task_.reset(
new StartTask(this, params->script_url, std::move(request)));
@@ -476,8 +504,15 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
// Abort an inflight start task.
inflight_start_task_.reset();
- ServiceWorkerStatusCode status =
- registry_->StopWorker(process_id(), embedded_worker_id_);
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_IPC_FAILED;
+ if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) {
+ status = SERVICE_WORKER_OK;
+ client_->StopWorker(base::Bind(&EmbeddedWorkerRegistry::OnWorkerStopped,
+ base::Unretained(registry_.get()),
+ process_id(), embedded_worker_id()));
+ } else {
+ status = registry_->StopWorker(process_id(), embedded_worker_id_);
+ }
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.SendStopWorker.Status", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
// StopWorker could fail if we were starting up and don't have a process yet,
@@ -488,7 +523,8 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
}
status_ = EmbeddedWorkerStatus::STOPPING;
- FOR_EACH_OBSERVER(Listener, listener_list_, OnStopping());
+ for (auto& observer : listener_list_)
+ observer.OnStopping();
return status;
}
@@ -529,14 +565,16 @@ void EmbeddedWorkerInstance::ResumeAfterDownload() {
embedded_worker_id_));
}
-shell::InterfaceRegistry* EmbeddedWorkerInstance::GetInterfaceRegistry() {
+service_manager::InterfaceRegistry*
+EmbeddedWorkerInstance::GetInterfaceRegistry() {
DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
status_ == EmbeddedWorkerStatus::RUNNING)
<< static_cast<int>(status_);
return interface_registry_.get();
}
-shell::InterfaceProvider* EmbeddedWorkerInstance::GetRemoteInterfaces() {
+service_manager::InterfaceProvider*
+EmbeddedWorkerInstance::GetRemoteInterfaces() {
DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
status_ == EmbeddedWorkerStatus::RUNNING)
<< static_cast<int>(status_);
@@ -565,7 +603,8 @@ void EmbeddedWorkerInstance::OnProcessAllocated(
process_handle_ = std::move(handle);
starting_phase_ = REGISTERING_TO_DEVTOOLS;
start_situation_ = start_situation;
- FOR_EACH_OBSERVER(Listener, listener_list_, OnProcessAllocated());
+ for (auto& observer : listener_list_)
+ observer.OnProcessAllocated();
}
void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
@@ -582,16 +621,30 @@ void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
// we set the NULL time here.
step_time_ = base::TimeTicks();
}
- FOR_EACH_OBSERVER(Listener, listener_list_, OnRegisteredToDevToolsManager());
+ for (auto& observer : listener_list_)
+ observer.OnRegisteredToDevToolsManager();
}
-void EmbeddedWorkerInstance::SendMojoStartWorker(
+ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMojoStartWorker(
std::unique_ptr<EmbeddedWorkerStartParams> params) {
- client_->StartWorker(*params);
+ if (!context_)
+ return SERVICE_WORKER_ERROR_ABORT;
+ service_manager::mojom::InterfaceProviderPtr remote_interfaces;
+ service_manager::mojom::InterfaceProviderRequest request =
+ mojo::GetProxy(&remote_interfaces);
+ remote_interfaces_->Bind(std::move(remote_interfaces));
+ service_manager::mojom::InterfaceProviderPtr exposed_interfaces;
+ interface_registry_->Bind(
+ mojo::GetProxy(&exposed_interfaces), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec(), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec());
+ client_->StartWorker(*params, std::move(exposed_interfaces),
+ std::move(request));
registry_->BindWorkerToProcess(process_id(), embedded_worker_id());
TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start",
this, "SendStartWorker", "Status", "mojo");
OnStartWorkerMessageSent();
+ return SERVICE_WORKER_OK;
}
void EmbeddedWorkerInstance::OnStartWorkerMessageSent() {
@@ -604,7 +657,8 @@ void EmbeddedWorkerInstance::OnStartWorkerMessageSent() {
}
starting_phase_ = SENT_START_WORKER;
- FOR_EACH_OBSERVER(Listener, listener_list_, OnStartWorkerMessageSent());
+ for (auto& observer : listener_list_)
+ observer.OnStartWorkerMessageSent();
}
void EmbeddedWorkerInstance::OnReadyForInspection() {
@@ -645,7 +699,8 @@ void EmbeddedWorkerInstance::OnScriptLoaded() {
}
starting_phase_ = SCRIPT_LOADED;
- FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoaded());
+ for (auto& observer : listener_list_)
+ observer.OnScriptLoaded();
// |this| may be destroyed by the callback.
}
@@ -685,19 +740,28 @@ void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
}
thread_id_ = thread_id;
- FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted());
-
- shell::mojom::InterfaceProviderPtr exposed_interfaces;
- interface_registry_->Bind(mojo::GetProxy(&exposed_interfaces));
- shell::mojom::InterfaceProviderPtr remote_interfaces;
- shell::mojom::InterfaceProviderRequest request =
- mojo::GetProxy(&remote_interfaces);
- remote_interfaces_->Bind(std::move(remote_interfaces));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(SetupMojoOnUIThread, process_id(), thread_id_,
- base::Passed(&request),
- base::Passed(exposed_interfaces.PassInterface())));
+ for (auto& observer : listener_list_)
+ observer.OnThreadStarted();
+
+ // This code is for BackgroundSync and FetchEvent, which have been already
+ // mojofied. Interfaces are exchanged at StartWorker when mojo for the service
+ // worker is enabled, so this code isn't necessary when the flag is enabled.
+ if (!ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) {
+ service_manager::mojom::InterfaceProviderPtr exposed_interfaces;
+ interface_registry_->Bind(
+ mojo::GetProxy(&exposed_interfaces), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec(), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec());
+ service_manager::mojom::InterfaceProviderPtr remote_interfaces;
+ service_manager::mojom::InterfaceProviderRequest request =
+ mojo::GetProxy(&remote_interfaces);
+ remote_interfaces_->Bind(std::move(remote_interfaces));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(SetupMojoOnUIThread, process_id(), thread_id_,
+ base::Passed(&request),
+ base::Passed(exposed_interfaces.PassInterface())));
+ }
}
void EmbeddedWorkerInstance::OnScriptLoadFailed() {
@@ -706,7 +770,8 @@ void EmbeddedWorkerInstance::OnScriptLoadFailed() {
TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start",
inflight_start_task_.get(),
"OnScriptLoadFailed");
- FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoadFailed());
+ for (auto& observer : listener_list_)
+ observer.OnScriptLoadFailed();
}
void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
@@ -740,23 +805,26 @@ void EmbeddedWorkerInstance::OnStarted() {
DCHECK(status_ == EmbeddedWorkerStatus::STARTING);
status_ = EmbeddedWorkerStatus::RUNNING;
inflight_start_task_.reset();
- FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted());
+ for (auto& observer : listener_list_)
+ observer.OnStarted();
}
void EmbeddedWorkerInstance::OnStopped() {
EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
- FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped(old_status));
+ for (auto& observer : listener_list_)
+ observer.OnStopped(old_status);
}
void EmbeddedWorkerInstance::OnDetached() {
EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
- FOR_EACH_OBSERVER(Listener, listener_list_, OnDetached(old_status));
+ for (auto& observer : listener_list_)
+ observer.OnDetached(old_status);
}
void EmbeddedWorkerInstance::Detach() {
- registry_->RemoveWorker(process_id(), embedded_worker_id_);
+ registry_->DetachWorker(process_id(), embedded_worker_id());
OnDetached();
}
@@ -765,9 +833,8 @@ base::WeakPtr<EmbeddedWorkerInstance> EmbeddedWorkerInstance::AsWeakPtr() {
}
bool EmbeddedWorkerInstance::OnMessageReceived(const IPC::Message& message) {
- ListenerList::Iterator it(&listener_list_);
- while (Listener* listener = it.GetNext()) {
- if (listener->OnMessageReceived(message))
+ for (auto& listener : listener_list_) {
+ if (listener.OnMessageReceived(message))
return true;
}
return false;
@@ -778,10 +845,10 @@ void EmbeddedWorkerInstance::OnReportException(
int line_number,
int column_number,
const GURL& source_url) {
- FOR_EACH_OBSERVER(
- Listener,
- listener_list_,
- OnReportException(error_message, line_number, column_number, source_url));
+ for (auto& observer : listener_list_) {
+ observer.OnReportException(error_message, line_number, column_number,
+ source_url);
+ }
}
void EmbeddedWorkerInstance::OnReportConsoleMessage(
@@ -790,11 +857,10 @@ void EmbeddedWorkerInstance::OnReportConsoleMessage(
const base::string16& message,
int line_number,
const GURL& source_url) {
- FOR_EACH_OBSERVER(
- Listener,
- listener_list_,
- OnReportConsoleMessage(
- source_identifier, message_level, message, line_number, source_url));
+ for (auto& observer : listener_list_) {
+ observer.OnReportConsoleMessage(source_identifier, message_level, message,
+ line_number, source_url);
+ }
}
int EmbeddedWorkerInstance::process_id() const {
@@ -836,6 +902,7 @@ void EmbeddedWorkerInstance::ReleaseProcess() {
// Abort an inflight start task.
inflight_start_task_.reset();
+ client_.reset();
devtools_proxy_.reset();
process_handle_.reset();
status_ = EmbeddedWorkerStatus::STOPPED;
@@ -850,9 +917,10 @@ void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback,
ReleaseProcess();
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
callback.Run(status);
- if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED)
- FOR_EACH_OBSERVER(Listener, weak_this->listener_list_,
- OnStopped(old_status));
+ if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED) {
+ for (auto& observer : weak_this->listener_list_)
+ observer.OnStopped(old_status);
+ }
}
base::TimeDelta EmbeddedWorkerInstance::UpdateStepTime() {
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 705b7735298..e6f4d9d754f 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -37,7 +37,7 @@ namespace IPC {
class Message;
}
-namespace shell {
+namespace service_manager {
class InterfaceProvider;
class InterfaceRegistry;
}
@@ -134,11 +134,12 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
// Resumes the worker if it paused after download.
void ResumeAfterDownload();
- // Returns the shell::InterfaceRegistry and shell::InterfaceProvider for this
+ // Returns the service_manager::InterfaceRegistry and
+ // service_manager::InterfaceProvider for this
// worker. It is invalid to call this when the worker is not in STARTING or
// RUNNING status.
- shell::InterfaceRegistry* GetInterfaceRegistry();
- shell::InterfaceProvider* GetRemoteInterfaces();
+ service_manager::InterfaceRegistry* GetInterfaceRegistry();
+ service_manager::InterfaceProvider* GetRemoteInterfaces();
int embedded_worker_id() const { return embedded_worker_id_; }
EmbeddedWorkerStatus status() const { return status_; }
@@ -225,7 +226,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
bool wait_for_debugger);
// Sends StartWorker message via Mojo.
- void SendMojoStartWorker(std::unique_ptr<EmbeddedWorkerStartParams> params);
+ ServiceWorkerStatusCode SendMojoStartWorker(
+ std::unique_ptr<EmbeddedWorkerStartParams> params);
// Called back from StartTask after a start worker message is sent.
void OnStartWorkerMessageSent();
@@ -311,8 +313,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
int thread_id_;
// These are connected to the renderer process after OnThreadStarted.
- std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
- std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
+ std::unique_ptr<service_manager::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
// |client_| is used to send messages to the renderer process.
mojom::EmbeddedWorkerInstanceClientPtr client_;
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 1253a28f20a..1ded6ee740f 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -17,9 +17,11 @@
#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_test_utils.h"
#include "content/common/service_worker/embedded_worker.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_utils.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -120,6 +122,12 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
+ std::vector<std::unique_ptr<
+ EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient>>*
+ mock_instance_clients() {
+ return helper_->mock_instance_clients();
+ }
+
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
std::vector<EventLog> events_;
@@ -128,23 +136,8 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
};
-class EmbeddedWorkerInstanceTestP : public EmbeddedWorkerInstanceTest,
- public testing::WithParamInterface<bool> {
- protected:
- void SetUp() override {
- is_mojo_enabled_ = GetParam();
- if (is_mojo_enabled()) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kMojoServiceWorker);
- }
- EmbeddedWorkerInstanceTest::SetUp();
- }
-
- bool is_mojo_enabled() { return is_mojo_enabled_; }
-
- private:
- bool is_mojo_enabled_ = false;
-};
+class EmbeddedWorkerInstanceTestP
+ : public MojoServiceWorkerTestP<EmbeddedWorkerInstanceTest> {};
// A helper to simulate the start worker sequence is stalled in a worker
// process.
@@ -226,13 +219,13 @@ TEST_P(EmbeddedWorkerInstanceTestP, StartAndStop) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
if (!is_mojo_enabled()) {
- // Verify that we've sent two messages to start and terminate the worker.
+ // Verify that we've sent two messages via chromium IPC to start and
+ // terminate the worker.
ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
EmbeddedWorkerMsg_StartWorker::ID));
+ ASSERT_TRUE(
+ ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StopWorker::ID));
}
- // StopWorker should be sent in either case.
- ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StopWorker::ID));
// Check if the IPCs are fired in expected order.
ASSERT_EQ(4u, events_.size());
@@ -244,7 +237,7 @@ TEST_P(EmbeddedWorkerInstanceTestP, StartAndStop) {
// Test that a worker that failed twice will use a new render process
// on the next attempt.
-TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
+TEST_P(EmbeddedWorkerInstanceTestP, ForceNewProcess) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
@@ -308,7 +301,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
}
}
-TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
+TEST_P(EmbeddedWorkerInstanceTestP, StopWhenDevToolsAttached) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
@@ -355,7 +348,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
// Test that the removal of a worker from the registry doesn't remove
// other workers in the same process.
-TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
+TEST_P(EmbeddedWorkerInstanceTestP, RemoveWorkerInSharedProcess) {
std::unique_ptr<EmbeddedWorkerInstance> worker1 =
embedded_worker_registry()->CreateWorker();
std::unique_ptr<EmbeddedWorkerInstance> worker2 =
@@ -410,7 +403,7 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
worker2->Stop();
}
-TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
+TEST_P(EmbeddedWorkerInstanceTestP, DetachDuringProcessAllocation) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -441,7 +434,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
}
-TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
+TEST_P(EmbeddedWorkerInstanceTestP, DetachAfterSendingStartWorkerMessage) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -480,7 +473,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
}
-TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
+TEST_P(EmbeddedWorkerInstanceTestP, StopDuringProcessAllocation) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -509,7 +502,13 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ if (is_mojo_enabled()) {
+ // STOPPING should be recorded here because EmbeddedWorkerInstance must be
+ // detached while executing RunUntilIdle.
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, events_[0].status);
+ } else {
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ }
events_.clear();
// Restart the worker.
@@ -530,7 +529,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
worker->Stop();
}
-TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
+TEST_P(EmbeddedWorkerInstanceTestP, StopDuringPausedAfterDownload) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -561,7 +560,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
EmbeddedWorkerMsg_ResumeAfterDownload::ID));
}
-TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
+TEST_P(EmbeddedWorkerInstanceTestP, StopAfterSendingStartWorkerMessage) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -622,7 +621,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
worker->Stop();
}
-TEST_F(EmbeddedWorkerInstanceTest, Detach) {
+TEST_P(EmbeddedWorkerInstanceTestP, Detach) {
const int64_t version_id = 55L;
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -654,13 +653,18 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
}
// Test for when sending the start IPC failed.
-TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
- helper_.reset(new FailToSendIPCHelper());
-
+TEST_P(EmbeddedWorkerInstanceTestP, FailToSendStartIPC) {
const int64_t version_id = 55L;
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
+ if (is_mojo_enabled()) {
+ // Let StartWorker fail; mojo IPC fails to connect to a remote interface.
+ helper_->RegisterMockInstanceClient(nullptr);
+ } else {
+ helper_.reset(new FailToSendIPCHelper());
+ }
+
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
helper_->SimulateAddProcessToPattern(pattern,
@@ -669,19 +673,86 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
worker->AddListener(this);
// Attempt to start the worker.
- base::RunLoop run_loop;
std::unique_ptr<EmbeddedWorkerStartParams> params(
CreateStartParams(version_id, pattern, url));
- worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
- run_loop.QuitClosure()));
- run_loop.Run();
+ if (is_mojo_enabled()) {
+ worker->Start(std::move(params),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+ } else {
+ base::RunLoop run_loop;
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
+ run_loop.Run();
+ }
- // The callback should have run, and we should have got an OnStopped message.
- EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status);
- ASSERT_EQ(2u, events_.size());
+ if (is_mojo_enabled()) {
+ // Worker should handle the failure of binding 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);
+ } else {
+ // The callback should have run, and we should have got an OnStopped
+ // message.
+ EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status);
+ ASSERT_EQ(2u, events_.size());
+ EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
+ EXPECT_EQ(STOPPED, events_[1].type);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
+ }
+}
+
+class FailEmbeddedWorkerInstanceClientImpl
+ : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient {
+ public:
+ explicit FailEmbeddedWorkerInstanceClientImpl(
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+ : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
+
+ private:
+ void StartWorker(
+ const EmbeddedWorkerStartParams& /* unused */,
+ service_manager::mojom::InterfaceProviderPtr /* unused */,
+ service_manager::mojom::InterfaceProviderRequest /* unused */) override {
+ helper_->mock_instance_clients()->clear();
+ }
+};
+
+TEST_P(EmbeddedWorkerInstanceTestP, RemoveRemoteInterface) {
+ if (!is_mojo_enabled())
+ return;
+
+ const int64_t version_id = 55L;
+ const GURL pattern("http://example.com/");
+ const GURL url("http://example.com/worker.js");
+
+ // Let StartWorker fail; binding is discarded in the middle of IPC
+ helper_->RegisterMockInstanceClient(
+ base::MakeUnique<FailEmbeddedWorkerInstanceClientImpl>(
+ helper_->AsWeakPtr()));
+ ASSERT_EQ(mock_instance_clients()->size(), 1UL);
+
+ std::unique_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker();
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->mock_render_process_id());
+ worker->AddListener(this);
+
+ // Attempt to start the worker.
+ std::unique_ptr<EmbeddedWorkerStartParams> params(
+ CreateStartParams(version_id, pattern, url));
+ worker->Start(std::move(params),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+
+ // Worker should handle the sudden shutdown as detach.
+ ASSERT_EQ(3u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
- EXPECT_EQ(STOPPED, events_[1].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
+ EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
+ EXPECT_EQ(DETACHED, events_[2].type);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
}
INSTANTIATE_TEST_CASE_P(EmbeddedWorkerInstanceTest,
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index d86cdef643b..fff48b95cdc 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -300,7 +300,13 @@ ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
void EmbeddedWorkerRegistry::RemoveWorker(int process_id,
int embedded_worker_id) {
DCHECK(base::ContainsKey(worker_map_, embedded_worker_id));
+ DetachWorker(process_id, embedded_worker_id);
worker_map_.erase(embedded_worker_id);
+}
+
+void EmbeddedWorkerRegistry::DetachWorker(int process_id,
+ int embedded_worker_id) {
+ DCHECK(base::ContainsKey(worker_map_, embedded_worker_id));
if (!base::ContainsKey(worker_process_map_, process_id))
return;
worker_process_map_[process_id].erase(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 70475efb5be..80ce9b3db64 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.h
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -109,9 +109,10 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
private:
friend class base::RefCounted<EmbeddedWorkerRegistry>;
+ friend class MojoEmbeddedWorkerInstanceTest;
friend class EmbeddedWorkerInstance;
friend class EmbeddedWorkerInstanceTest;
- FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest,
+ FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTestP,
RemoveWorkerInSharedProcess);
using WorkerInstanceMap = std::map<int, EmbeddedWorkerInstance*>;
@@ -135,6 +136,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.
+ void DetachWorker(int process_id, int embedded_worker_id);
EmbeddedWorkerInstance* GetWorkerForMessage(int process_id,
int embedded_worker_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 674827f44c3..dd776ebe2bd 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -22,14 +22,15 @@
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/embedded_worker_setup.mojom.h"
#include "content/common/service_worker/embedded_worker_start_params.h"
+#include "content/common/service_worker/fetch_event_dispatcher.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
#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/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -71,8 +72,8 @@ class EmbeddedWorkerTestHelper::MockEmbeddedWorkerSetup
void ExchangeInterfaceProviders(
int32_t thread_id,
- shell::mojom::InterfaceProviderRequest request,
- shell::mojom::InterfaceProviderPtr remote_interfaces) override {
+ service_manager::mojom::InterfaceProviderRequest request,
+ service_manager::mojom::InterfaceProviderPtr remote_interfaces) override {
if (!helper_)
return;
helper_->OnSetupMojoStub(thread_id, std::move(request),
@@ -92,7 +93,9 @@ EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
~MockEmbeddedWorkerInstanceClient() {}
void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
- const EmbeddedWorkerStartParams& params) {
+ const EmbeddedWorkerStartParams& params,
+ service_manager::mojom::InterfaceProviderPtr browser_interfaces,
+ service_manager::mojom::InterfaceProviderRequest renderer_request) {
if (!helper_)
return;
@@ -105,10 +108,29 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
- helper_->weak_factory_.GetWeakPtr(), params.embedded_worker_id,
- params.service_worker_version_id, params.scope,
- params.script_url, params.pause_after_download));
+ base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, helper_->AsWeakPtr(),
+ params.embedded_worker_id, params.service_worker_version_id,
+ params.scope, params.script_url, params.pause_after_download));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnSetupMojoStub,
+ helper_->AsWeakPtr(), worker->thread_id(),
+ base::Passed(&renderer_request),
+ base::Passed(&browser_interfaces)));
+}
+
+void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker(
+ const StopWorkerCallback& callback) {
+ if (!helper_)
+ return;
+
+ ASSERT_TRUE(embedded_worker_id_);
+ EmbeddedWorkerInstance* worker =
+ helper_->registry()->GetWorker(embedded_worker_id_.value());
+ // |worker| is possible to be null when corresponding EmbeddedWorkerInstance
+ // is removed right after sending StopWorker.
+ if (worker)
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
+ callback.Run();
}
// static
@@ -132,6 +154,39 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
client->binding_.Bind(std::move(request));
}
+class EmbeddedWorkerTestHelper::MockFetchEventDispatcher
+ : public NON_EXPORTED_BASE(mojom::FetchEventDispatcher) {
+ public:
+ static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ int thread_id,
+ mojom::FetchEventDispatcherRequest request) {
+ mojo::MakeStrongBinding(
+ base::MakeUnique<MockFetchEventDispatcher>(helper, thread_id),
+ std::move(request));
+ }
+
+ MockFetchEventDispatcher(
+ const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ int thread_id)
+ : helper_(helper), thread_id_(thread_id) {}
+
+ ~MockFetchEventDispatcher() override {}
+
+ void DispatchFetchEvent(int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const DispatchFetchEventCallback& callback) override {
+ if (!helper_)
+ return;
+ helper_->OnFetchEventStub(thread_id_, fetch_event_id, request,
+ std::move(preload_handle), callback);
+ }
+
+ private:
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
+ const int thread_id_;
+};
+
EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
const base::FilePath& user_data_directory)
: browser_context_(new TestBrowserContext),
@@ -199,6 +254,11 @@ bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void EmbeddedWorkerTestHelper::RegisterMockInstanceClient(
+ std::unique_ptr<MockEmbeddedWorkerInstanceClient> client) {
+ mock_instance_clients_.push_back(std::move(client));
+}
+
ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() {
return wrapper_->context();
}
@@ -243,7 +303,6 @@ bool EmbeddedWorkerTestHelper::OnMessageToWorker(int thread_id,
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ExtendableMessageEvent,
OnExtendableMessageEventStub)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEventStub)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEventStub)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEventStub)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -253,7 +312,12 @@ bool EmbeddedWorkerTestHelper::OnMessageToWorker(int thread_id,
}
void EmbeddedWorkerTestHelper::OnSetupMojo(
- shell::InterfaceRegistry* interface_registry) {}
+ int thread_id,
+ service_manager::InterfaceRegistry* interface_registry) {
+ interface_registry->AddInterface(base::Bind(&MockFetchEventDispatcher::Create,
+ weak_factory_.GetWeakPtr(),
+ thread_id));
+}
void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
int request_id) {
@@ -281,11 +345,12 @@ void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
void EmbeddedWorkerTestHelper::OnFetchEvent(
int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) {
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id, response_id,
+ embedded_worker_id, fetch_event_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -295,9 +360,7 @@ void EmbeddedWorkerTestHelper::OnFetchEvent(
std::string() /* cache_storage_cache_name */,
ServiceWorkerHeaderList() /* cors_exposed_header_names */),
base::Time::Now()));
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, event_finish_id,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback.Run(SERVICE_WORKER_OK, base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnPushEvent(int embedded_worker_id,
@@ -342,6 +405,7 @@ void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted(
int thread_id,
int embedded_worker_id) {
+ thread_id_embedded_worker_id_map_[thread_id] = embedded_worker_id;
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker != NULL);
registry()->OnWorkerThreadStarted(worker->process_id(), thread_id,
@@ -382,10 +446,9 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
- weak_factory_.GetWeakPtr(), params.embedded_worker_id,
- params.service_worker_version_id, params.scope,
- params.script_url, params.pause_after_download));
+ base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
+ params.embedded_worker_id, params.service_worker_version_id,
+ params.scope, params.script_url, params.pause_after_download));
}
void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
@@ -394,7 +457,7 @@ void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
ASSERT_TRUE(worker);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
- weak_factory_.GetWeakPtr(), embedded_worker_id));
+ AsWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
@@ -402,7 +465,7 @@ void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
ASSERT_TRUE(worker != NULL);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
- weak_factory_.GetWeakPtr(), embedded_worker_id));
+ AsWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
@@ -416,65 +479,69 @@ void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
FROM_HERE,
base::Bind(
base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker),
- weak_factory_.GetWeakPtr(), thread_id, embedded_worker_id, message));
+ AsWeakPtr(), thread_id, embedded_worker_id, message));
}
void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
- weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_, request_id));
+ FROM_HERE,
+ base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent, AsWeakPtr(),
+ current_embedded_worker_id_, request_id));
}
void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
int request_id,
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
- weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_, request_id));
+ FROM_HERE,
+ base::Bind(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
+ AsWeakPtr(), current_embedded_worker_id_, request_id));
}
void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent,
- weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_, request_id));
+ FROM_HERE,
+ base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent, AsWeakPtr(),
+ current_embedded_worker_id_, request_id));
}
void EmbeddedWorkerTestHelper::OnFetchEventStub(
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) {
+ int thread_id,
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent,
- weak_factory_.GetWeakPtr(), current_embedded_worker_id_,
- response_id, event_finish_id, request));
+ base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
+ thread_id_embedded_worker_id_map_[thread_id], fetch_event_id,
+ request, base::Passed(&preload_handle), callback));
}
void EmbeddedWorkerTestHelper::OnPushEventStub(
int request_id,
const PushEventPayload& payload) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnPushEvent,
- weak_factory_.GetWeakPtr(),
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnPushEvent, AsWeakPtr(),
current_embedded_worker_id_, request_id, payload));
}
void EmbeddedWorkerTestHelper::OnSetupMojoStub(
int thread_id,
- shell::mojom::InterfaceProviderRequest request,
- shell::mojom::InterfaceProviderPtr remote_interfaces) {
- std::unique_ptr<shell::InterfaceRegistry> local(
- new shell::InterfaceRegistry);
- local->Bind(std::move(request));
-
- std::unique_ptr<shell::InterfaceProvider> remote(
- new shell::InterfaceProvider);
+ service_manager::mojom::InterfaceProviderRequest request,
+ service_manager::mojom::InterfaceProviderPtr remote_interfaces) {
+ auto local =
+ base::MakeUnique<service_manager::InterfaceRegistry>(std::string());
+ local->Bind(std::move(request), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec(),
+ service_manager::Identity(),
+ service_manager::InterfaceProviderSpec());
+
+ std::unique_ptr<service_manager::InterfaceProvider> remote(
+ new service_manager::InterfaceProvider);
remote->Bind(std::move(remote_interfaces));
- OnSetupMojo(local.get());
+ OnSetupMojo(thread_id, local.get());
InterfaceRegistryAndProvider pair(std::move(local), std::move(remote));
thread_id_service_registry_map_[thread_id] = std::move(pair);
}
@@ -492,20 +559,23 @@ EmbeddedWorkerTestHelper::NewMessagePortMessageFilter() {
return filter.get();
}
-std::unique_ptr<shell::InterfaceRegistry>
+std::unique_ptr<service_manager::InterfaceRegistry>
EmbeddedWorkerTestHelper::CreateInterfaceRegistry(MockRenderProcessHost* rph) {
- std::unique_ptr<shell::InterfaceRegistry> registry(
- new shell::InterfaceRegistry);
+ auto registry =
+ base::MakeUnique<service_manager::InterfaceRegistry>(std::string());
+ registry->AddInterface(
+ base::Bind(&MockEmbeddedWorkerSetup::Create, AsWeakPtr()));
registry->AddInterface(
- base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
- registry->AddInterface(base::Bind(&MockEmbeddedWorkerInstanceClient::Bind,
- weak_factory_.GetWeakPtr()));
+ base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr()));
- shell::mojom::InterfaceProviderPtr interfaces;
- registry->Bind(mojo::GetProxy(&interfaces));
+ service_manager::mojom::InterfaceProviderPtr interfaces;
+ registry->Bind(mojo::GetProxy(&interfaces), service_manager::Identity(),
+ service_manager::InterfaceProviderSpec(),
+ service_manager::Identity(),
+ service_manager::InterfaceProviderSpec());
- std::unique_ptr<shell::InterfaceProvider> remote_interfaces(
- new shell::InterfaceProvider);
+ std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces(
+ new service_manager::InterfaceProvider);
remote_interfaces->Bind(std::move(interfaces));
rph->SetRemoteInterfaces(std::move(remote_interfaces));
return 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 97ec1637725..5555f2f50b3 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -16,18 +16,23 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "base/time/time.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
+#include "content/common/service_worker/fetch_event_dispatcher.mojom.h"
+#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 "services/shell/public/interfaces/interface_provider.mojom.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
class GURL;
struct ServiceWorkerMsg_ExtendableMessageEvent_Params;
-namespace shell {
+namespace service_manager {
class InterfaceProvider;
class InterfaceRegistry;
}
@@ -63,6 +68,10 @@ struct ServiceWorkerFetchRequest;
class EmbeddedWorkerTestHelper : public IPC::Sender,
public IPC::Listener {
public:
+ using FetchCallback =
+ base::Callback<void(ServiceWorkerStatusCode,
+ base::Time /* dispatch_event_time */)>;
+
class MockEmbeddedWorkerInstanceClient
: public mojom::EmbeddedWorkerInstanceClient {
public:
@@ -73,15 +82,21 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
static void Bind(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
mojom::EmbeddedWorkerInstanceClientRequest request);
- private:
+ protected:
// Implementation of mojo interfaces.
- void StartWorker(const EmbeddedWorkerStartParams& params) override;
+ void StartWorker(
+ const EmbeddedWorkerStartParams& params,
+ service_manager::mojom::InterfaceProviderPtr browser_interfaces,
+ service_manager::mojom::InterfaceProviderRequest renderer_request)
+ override;
+ void StopWorker(const StopWorkerCallback& callback) override;
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
base::Optional<int> embedded_worker_id_;
+ private:
DISALLOW_COPY_AND_ASSIGN(MockEmbeddedWorkerInstanceClient);
};
@@ -100,6 +115,14 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& msg) override;
+ // Register a mojo endpoint object derived from
+ // MockEmbeddedWorkerInstanceClient.
+ void RegisterMockInstanceClient(
+ std::unique_ptr<MockEmbeddedWorkerInstanceClient> client);
+
+ template <typename MockType, typename... Args>
+ MockType* CreateAndRegisterMockInstanceClient(Args&&... args);
+
// IPC sink for EmbeddedWorker messages.
IPC::TestSink* ipc_sink() { return &sink_; }
// Inner IPC sink for script context messages sent via EmbeddedWorker.
@@ -130,6 +153,10 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
TestBrowserContext* browser_context() { return browser_context_.get(); }
+ base::WeakPtr<EmbeddedWorkerTestHelper> AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
protected:
// Called when StartWorker, StopWorker and SendMessageToWorker message
// is sent to the embedded worker. Override if necessary. By default
@@ -150,7 +177,9 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// Called to setup mojo for a new embedded worker. Override to register
// interfaces the worker should expose to the browser.
- virtual void OnSetupMojo(shell::InterfaceRegistry* interface_registry);
+ virtual void OnSetupMojo(
+ int thread_id,
+ service_manager::InterfaceRegistry* interface_registry);
// On*Event handlers. Called by the default implementation of
// OnMessageToWorker when events are sent to the embedded
@@ -160,9 +189,10 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
virtual void OnExtendableMessageEvent(int embedded_worker_id, int request_id);
virtual void OnInstallEvent(int embedded_worker_id, int request_id);
virtual void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request);
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback);
virtual void OnPushEvent(int embedded_worker_id,
int request_id,
const PushEventPayload& payload);
@@ -182,10 +212,11 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
private:
using InterfaceRegistryAndProvider =
- std::pair<std::unique_ptr<shell::InterfaceRegistry>,
- std::unique_ptr<shell::InterfaceProvider>>;
+ std::pair<std::unique_ptr<service_manager::InterfaceRegistry>,
+ std::unique_ptr<service_manager::InterfaceProvider>>;
class MockEmbeddedWorkerSetup;
+ class MockFetchEventDispatcher;
void OnStartWorkerStub(const EmbeddedWorkerStartParams& params);
void OnResumeAfterDownloadStub(int embedded_worker_id);
@@ -198,17 +229,20 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
int request_id,
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEventStub(int request_id);
- void OnFetchEventStub(int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request);
+ void OnFetchEventStub(int thread_id,
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback);
void OnPushEventStub(int request_id, const PushEventPayload& payload);
- void OnSetupMojoStub(int thread_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services);
+ void OnSetupMojoStub(
+ int thread_id,
+ service_manager::mojom::InterfaceProviderRequest services,
+ service_manager::mojom::InterfaceProviderPtr exposed_services);
MessagePortMessageFilter* NewMessagePortMessageFilter();
- std::unique_ptr<shell::InterfaceRegistry> CreateInterfaceRegistry(
+ std::unique_ptr<service_manager::InterfaceRegistry> CreateInterfaceRegistry(
MockRenderProcessHost* rph);
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -228,11 +262,14 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
int mock_render_process_id_;
int new_mock_render_process_id_;
- std::unique_ptr<shell::InterfaceRegistry> render_process_interface_registry_;
- std::unique_ptr<shell::InterfaceRegistry>
+ std::unique_ptr<service_manager::InterfaceRegistry>
+ render_process_interface_registry_;
+ std::unique_ptr<service_manager::InterfaceRegistry>
new_render_process_interface_registry_;
std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map_;
+ std::map<int /* thread_id */, int /* embedded_worker_id */>
+ thread_id_embedded_worker_id_map_;
// Stores the InterfaceRegistry/InterfaceProviders that are associated with
// each individual service worker.
@@ -250,6 +287,16 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerTestHelper);
};
+template <typename MockType, typename... Args>
+MockType* EmbeddedWorkerTestHelper::CreateAndRegisterMockInstanceClient(
+ Args&&... args) {
+ std::unique_ptr<MockType> mock =
+ base::MakeUnique<MockType>(std::forward<Args>(args)...);
+ MockType* mock_rawptr = mock.get();
+ RegisterMockInstanceClient(std::move(mock));
+ return mock_rawptr;
+}
+
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_TEST_HELPER_H_
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 f3437802e4c..5298f1c7cf4 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
@@ -8,10 +8,12 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/stl_util.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/resource_request_body_impl.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_request_info.h"
@@ -92,8 +94,10 @@ void ForeignFetchRequestHandler::InitializeHandler(
if (ServiceWorkerUtils::IsMainResourceType(resource_type))
return;
- if (request->initiator().IsSameOriginWith(url::Origin(request->url())))
+ if (request->initiator().has_value() &&
+ request->initiator()->IsSameOriginWith(url::Origin(request->url()))) {
return;
+ }
if (!context_wrapper->OriginHasForeignFetchRegistrations(
request->url().GetOrigin())) {
@@ -218,7 +222,7 @@ void ForeignFetchRequestHandler::DidFindRegistration(
}
}
- const url::Origin& request_origin = job->request()->initiator();
+ const url::Origin& request_origin = job->request()->initiator().value();
bool origin_matches = active_version->foreign_fetch_origins().empty();
for (const url::Origin& origin : active_version->foreign_fetch_origins()) {
if (request_origin.IsSameOriginWith(origin))
@@ -230,6 +234,11 @@ void ForeignFetchRequestHandler::DidFindRegistration(
return;
}
+ if (!IsForeignFetchEnabled() && !CheckOriginTrialToken(active_version)) {
+ job->FallbackToNetwork();
+ return;
+ }
+
int render_process_id;
int render_frame_id;
if (!ResourceRequestInfo::GetRenderFrameForRequest(
@@ -270,4 +279,16 @@ void ForeignFetchRequestHandler::ClearJob() {
resource_context_ = nullptr;
}
+// static
+bool ForeignFetchRequestHandler::CheckOriginTrialToken(
+ const ServiceWorkerVersion* const active_version) {
+ // The worker entry in the database was written by old version Chrome (< M56)
+ // and the main script was not loaded yet. In this case, we can't check the
+ // origin trial token.
+ if (!active_version->origin_trial_tokens())
+ return true;
+ const auto& token_map = *active_version->origin_trial_tokens();
+ return base::ContainsKey(token_map, "ForeignFetch");
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/foreign_fetch_request_handler.h b/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
index 6a86d510bbd..48cb85e3960 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
@@ -32,11 +32,8 @@ namespace content {
class ResourceContext;
class ResourceRequestBodyImpl;
-class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
-class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
-struct ResourceResponseInfo;
// Class for routing network requests to ServiceWorkers for foreign fetch
// events. Created one per URLRequest and attached to each request.
@@ -86,6 +83,8 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
ResourceContext* resource_context);
private:
+ friend class ForeignFetchRequestHandlerTest;
+
ForeignFetchRequestHandler(
ServiceWorkerContextWrapper* context,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
@@ -113,6 +112,12 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
// that job.
void ClearJob();
+ // Returns true if the version doesn't have origin_trial_tokens entry (this
+ // happens if the existing worker's entry in the database was written by old
+ // version (< M56) Chrome), or the version has valid Origin Trial token.
+ static bool CheckOriginTrialToken(
+ const ServiceWorkerVersion* const active_version);
+
scoped_refptr<ServiceWorkerContextWrapper> context_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
ResourceType resource_type_;
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
new file mode 100644
index 00000000000..8a12374b641
--- /dev/null
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
@@ -0,0 +1,188 @@
+// 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/service_worker/foreign_fetch_request_handler.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_thread_impl.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_test_utils.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#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 "net/http/http_response_info.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// This is a sample public key for testing the API. The corresponding private
+// key (use this to generate new samples for this test file) is:
+//
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
+// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
+// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
+// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
+const uint8_t kTestPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+
+} // namespace
+
+class ForeignFetchRequestHandlerTest : public testing::Test {
+ public:
+ ForeignFetchRequestHandlerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
+ SetContentClient(&test_content_client_);
+ }
+ ~ForeignFetchRequestHandlerTest() override {}
+
+ void SetUp() override {
+ const GURL kScope("https://valid.example.com/scope/");
+ const GURL kResource1("https://valid.example.com/scope/sw.js");
+ const int64_t kRegistrationId = 0;
+ const int64_t kVersionId = 0;
+ helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ registration_ = new ServiceWorkerRegistration(kScope, kRegistrationId,
+ context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(registration_.get(), kResource1,
+ kVersionId, context()->AsWeakPtr());
+ }
+
+ void TearDown() override {
+ version_ = nullptr;
+ registration_ = nullptr;
+ helper_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ ServiceWorkerContextCore* context() const { return helper_->context(); }
+
+ bool CheckOriginTrialToken(const ServiceWorkerVersion* const version) const {
+ return ForeignFetchRequestHandler::CheckOriginTrialToken(version);
+ }
+
+ ServiceWorkerVersion* version() const { return version_.get(); }
+
+ static std::unique_ptr<net::HttpResponseInfo> CreateTestHttpResponseInfo() {
+ std::unique_ptr<net::HttpResponseInfo> http_info(
+ base::MakeUnique<net::HttpResponseInfo>());
+ http_info->ssl_info.cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+ DCHECK(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(""));
+ return http_info;
+ }
+
+ private:
+ class TestContentClient : public ContentClient {
+ public:
+ // ContentRendererClient methods
+ OriginTrialPolicy* GetOriginTrialPolicy() override {
+ return &origin_trial_policy_;
+ }
+
+ private:
+ class TestOriginTrialPolicy : public OriginTrialPolicy {
+ public:
+ base::StringPiece GetPublicKey() const override {
+ return base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
+ arraysize(kTestPublicKey));
+ }
+ bool IsFeatureDisabled(base::StringPiece feature) const override {
+ return false;
+ }
+ };
+
+ TestOriginTrialPolicy origin_trial_policy_;
+ };
+
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ TestContentClient test_content_client_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForeignFetchRequestHandlerTest);
+};
+
+TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_NoToken) {
+ EXPECT_TRUE(CheckOriginTrialToken(version()));
+ std::unique_ptr<net::HttpResponseInfo> http_info(
+ CreateTestHttpResponseInfo());
+ version()->SetMainScriptHttpResponseInfo(*http_info);
+ EXPECT_FALSE(CheckOriginTrialToken(version()));
+}
+
+TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_ValidToken) {
+ EXPECT_TRUE(CheckOriginTrialToken(version()));
+ std::unique_ptr<net::HttpResponseInfo> http_info(
+ CreateTestHttpResponseInfo());
+ const std::string kOriginTrial("Origin-Trial: ");
+ // Token for ForeignFetch which expires 2033-05-18.
+ // generate_token.py valid.example.com ForeignFetch
+ // --expire-timestamp=2000000000
+ // TODO(horo): Generate this sample token during the build.
+ const std::string kFeatureToken(
+ "AsDmvl17hoVfq9G6OT0VEhX28Nnl0VnbGZJoG6XFzosIamNfxNJ28m40PRA3PtFv3BfOlRe1"
+ "5bLrEZhtICdDnwwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGb3JlaWduRmV0Y2giLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0"
+ "=");
+ http_info->headers->AddHeader(kOriginTrial + kFeatureToken);
+ version()->SetMainScriptHttpResponseInfo(*http_info);
+ EXPECT_TRUE(CheckOriginTrialToken(version()));
+}
+
+TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_InvalidToken) {
+ EXPECT_TRUE(CheckOriginTrialToken(version()));
+ std::unique_ptr<net::HttpResponseInfo> http_info(
+ CreateTestHttpResponseInfo());
+ const std::string kOriginTrial("Origin-Trial: ");
+ // Token for FooBar which expires 2033-05-18.
+ // generate_token.py valid.example.com FooBar
+ // --expire-timestamp=2000000000
+ // TODO(horo): Generate this sample token during the build.
+ const std::string kFeatureToken(
+ "AqwtRpuoLdc6MKSFH8TbzoLFvLouL8VXTv6OJIqQvRtJBynRMbAbFwjUlcwMuj4pXUBbquBj"
+ "zj/w/d1H/ZsOcQIAAABWeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGb29CYXIiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=");
+ http_info->headers->AddHeader(kOriginTrial + kFeatureToken);
+ version()->SetMainScriptHttpResponseInfo(*http_info);
+ EXPECT_FALSE(CheckOriginTrialToken(version()));
+}
+
+TEST_F(ForeignFetchRequestHandlerTest, CheckOriginTrialToken_ExpiredToken) {
+ EXPECT_TRUE(CheckOriginTrialToken(version()));
+ std::unique_ptr<net::HttpResponseInfo> http_info(
+ CreateTestHttpResponseInfo());
+ const std::string kOriginTrial("Origin-Trial: ");
+ // Token for ForeignFetch which expired 2001-09-09.
+ // generate_token.py valid.example.com ForeignFetch
+ // --expire-timestamp=1000000000
+ const std::string kFeatureToken(
+ "AgBgj4Zhwzn85LJw7rzh4ZFRFqp49+9Es2SrCwZdDcoqtqQEjbvui4SKLn6GqMpr4DynGfJh"
+ "tIy9dpOuK8PVTwkAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGb3JlaWduRmV0Y2giLCAiZXhwaXJ5IjogMTAwMDAwMDAwMH0"
+ "=");
+ http_info->headers->AddHeader(kOriginTrial + kFeatureToken);
+ version()->SetMainScriptHttpResponseInfo(*http_info);
+ EXPECT_FALSE(CheckOriginTrialToken(version()));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/link_header_support.cc b/chromium/content/browser/service_worker/link_header_support.cc
index 6a8df7c2b69..b2364d8518e 100644
--- a/chromium/content/browser/service_worker/link_header_support.cc
+++ b/chromium/content/browser/service_worker/link_header_support.cc
@@ -16,6 +16,7 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
@@ -55,14 +56,29 @@ void HandleServiceWorkerLink(
ServiceWorkerContext* service_worker_context =
filter ? filter->service_worker_context()
: service_worker_context_for_testing;
+ if (IsBrowserSideNavigationEnabled() &&
+ ServiceWorkerUtils::IsMainResourceType(request_info->GetResourceType()) &&
+ !service_worker_context) {
+ service_worker_context = request_info->service_worker_context();
+ }
+
if (!service_worker_context)
return;
+ ServiceWorkerProviderHost* provider_host =
+ ServiceWorkerRequestHandler::GetProviderHost(request);
+
+ // If fetched from a service worker, make sure fetching service worker is
+ // controlling at least one client to prevent a service worker from spawning
+ // new service workers in the background.
+ if (provider_host && provider_host->IsHostToRunningServiceWorker()) {
+ if (!provider_host->running_hosted_version()->HasControllee())
+ return;
+ }
+
if (ServiceWorkerUtils::IsMainResourceType(request_info->GetResourceType())) {
// In case of navigations, make sure the navigation will actually result in
// a secure context.
- ServiceWorkerProviderHost* provider_host =
- ServiceWorkerRequestHandler::GetProviderHost(request);
if (!provider_host || !provider_host->IsContextSecureForServiceWorker())
return;
} else {
@@ -88,9 +104,10 @@ void HandleServiceWorkerLink(
if (!context_url.is_valid() || !script_url.is_valid() ||
!scope_url.is_valid())
return;
- if (!ServiceWorkerUtils::CanRegisterServiceWorker(context_url, scope_url,
- script_url))
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
+ {context_url, scope_url, script_url})) {
return;
+ }
std::string error;
if (ServiceWorkerUtils::ContainsDisallowedCharacter(scope_url, script_url,
&error))
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 34dfda9e24e..1b0598b7160 100644
--- a/chromium/content/browser/service_worker/link_header_support_unittest.cc
+++ b/chromium/content/browser/service_worker/link_header_support_unittest.cc
@@ -12,6 +12,8 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -48,6 +50,8 @@ SaveFoundRegistrations(
registrations);
}
+} // namespace
+
class LinkHeaderServiceWorkerTest : public ::testing::Test {
public:
LinkHeaderServiceWorkerTest()
@@ -64,8 +68,8 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
// An empty host.
std::unique_ptr<ServiceWorkerProviderHost> host(
new ServiceWorkerProviderHost(
- helper_->mock_render_process_id(), MSG_ROUTING_NONE,
- kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ render_process_id(), MSG_ROUTING_NONE, kMockProviderId,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED,
context()->AsWeakPtr(), nullptr));
provider_host_ = host->AsWeakPtr();
@@ -79,6 +83,28 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
return helper_->context_wrapper();
}
ServiceWorkerProviderHost* provider_host() { return provider_host_.get(); }
+ int render_process_id() const { return helper_->mock_render_process_id(); }
+
+ void CreateServiceWorkerProviderHost() {
+ std::unique_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(
+ render_process_id(), MSG_ROUTING_NONE, kMockProviderId,
+ SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
+ ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED,
+ context()->AsWeakPtr(), nullptr));
+ provider_host_ = host->AsWeakPtr();
+ context()->RemoveProviderHost(host->process_id(), host->provider_id());
+ context()->AddProviderHost(std::move(host));
+
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(GURL("https://host/scope"), 1L,
+ context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
+ registration.get(), GURL("https://host/script.js"), 1L,
+ context()->AsWeakPtr());
+
+ provider_host_->running_hosted_version_ = version;
+ }
std::unique_ptr<net::URLRequest> CreateRequest(const GURL& request_url,
ResourceType resource_type) {
@@ -95,11 +121,11 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
ServiceWorkerRequestHandler::InitializeHandler(
request.get(), context_wrapper(), &blob_storage_context_,
- helper_->mock_render_process_id(), kMockProviderId,
- false /* skip_service_worker */, FETCH_REQUEST_MODE_NO_CORS,
- FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE,
- resource_type, REQUEST_CONTEXT_TYPE_HYPERLINK,
- REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL, nullptr);
+ render_process_id(), kMockProviderId, false /* skip_service_worker */,
+ FETCH_REQUEST_MODE_NO_CORS, FETCH_CREDENTIALS_MODE_OMIT,
+ FetchRedirectMode::FOLLOW_MODE, resource_type,
+ REQUEST_CONTEXT_TYPE_HYPERLINK, REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ nullptr);
return request;
}
@@ -129,7 +155,10 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
storage::BlobStorageContext blob_storage_context_;
};
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
+class LinkHeaderServiceWorkerTestP
+ : public MojoServiceWorkerTestP<LinkHeaderServiceWorkerTest> {};
+
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_Basic) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
"<../foo.js>; rel=serviceworker", context_wrapper());
@@ -142,7 +171,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScopeWithFragment) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
"<../bar.js>; rel=serviceworker; scope=\"scope#ref\"", context_wrapper());
@@ -156,7 +185,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScopeAbsoluteUrl) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
"<bar.js>; rel=serviceworker; "
@@ -172,7 +201,8 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) {
+TEST_P(LinkHeaderServiceWorkerTestP,
+ InstallServiceWorker_ScopeDifferentOrigin) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
"<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"",
@@ -183,7 +213,8 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) {
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
+TEST_P(LinkHeaderServiceWorkerTestP,
+ InstallServiceWorker_ScopeUrlEncodedSlash) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
"<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"", context_wrapper());
@@ -193,7 +224,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_ScriptUrlEncodedSlash) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -204,7 +235,7 @@ TEST_F(LinkHeaderServiceWorkerTest,
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScriptAbsoluteUrl) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
"<https://example.com/bar.js>; rel=serviceworker; scope=foo",
@@ -218,7 +249,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_ScriptDifferentOrigin) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -230,7 +261,7 @@ TEST_F(LinkHeaderServiceWorkerTest,
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_MultipleWorkers) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
"<bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
@@ -248,7 +279,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
registrations[1].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_ValidAndInvalidValues) {
ProcessLinkHeaderForRequest(
CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -264,7 +295,7 @@ TEST_F(LinkHeaderServiceWorkerTest,
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_InsecureContext) {
+TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_InsecureContext) {
std::unique_ptr<net::URLRequest> request =
CreateSubresourceRequest(GURL("https://example.com/foo/bar/"));
ResourceRequestInfoImpl::ForRequest(request.get())
@@ -277,7 +308,7 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_InsecureContext) {
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_NavigationFromInsecureContextToSecureContext) {
std::unique_ptr<net::URLRequest> request = CreateRequest(
GURL("https://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME);
@@ -298,7 +329,7 @@ TEST_F(LinkHeaderServiceWorkerTest,
registrations[0].active_version.script_url);
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_NavigationToInsecureContext) {
provider_host()->SetDocumentUrl(GURL("http://example.com/foo/bar/"));
provider_host()->set_parent_frame_secure(true);
@@ -313,7 +344,7 @@ TEST_F(LinkHeaderServiceWorkerTest,
ASSERT_EQ(0u, registrations.size());
}
-TEST_F(LinkHeaderServiceWorkerTest,
+TEST_P(LinkHeaderServiceWorkerTestP,
InstallServiceWorker_NavigationToInsecureHttpsContext) {
provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/"));
provider_host()->set_parent_frame_secure(false);
@@ -328,6 +359,41 @@ TEST_F(LinkHeaderServiceWorkerTest,
ASSERT_EQ(0u, registrations.size());
}
-} // namespace
+TEST_P(LinkHeaderServiceWorkerTestP,
+ InstallServiceWorker_FromWorkerWithoutControllees) {
+ CreateServiceWorkerProviderHost();
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
+ "<../foo.js>; rel=serviceworker", context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_P(LinkHeaderServiceWorkerTestP,
+ InstallServiceWorker_FromWorkerWithControllees) {
+ CreateServiceWorkerProviderHost();
+
+ std::unique_ptr<ServiceWorkerProviderHost> controllee(
+ new ServiceWorkerProviderHost(
+ render_process_id(), MSG_ROUTING_NONE, kMockProviderId,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED,
+ context()->AsWeakPtr(), nullptr));
+ provider_host()->running_hosted_version()->AddControllee(controllee.get());
+
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
+ "<../foo.js>; rel=serviceworker", context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+}
+
+INSTANTIATE_TEST_CASE_P(LinkHeaderServiceWorkerTest,
+ LinkHeaderServiceWorkerTestP,
+ testing::Bool());
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 2d6129b62c8..6011d1ac2fc 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -12,12 +12,14 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -52,10 +54,10 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
#include "content/public/common/resource_type.h"
-#include "content/public/common/security_style.h"
#include "content/public/common/web_preferences.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -63,6 +65,7 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/test/test_content_browser_client.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log_with_source.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
@@ -335,22 +338,58 @@ void CountScriptResources(
*num_resources = static_cast<int>(version->script_cache_map()->size());
}
+void StoreString(std::string* result,
+ const base::Closure& callback,
+ const base::Value* value) {
+ value->GetAsString(result);
+ callback.Run();
+}
+
+int GetInt(const base::DictionaryValue& dict, base::StringPiece path) {
+ int out = 0;
+ EXPECT_TRUE(dict.GetInteger(path, &out));
+ return out;
+}
+
+std::string GetString(const base::DictionaryValue& dict,
+ base::StringPiece path) {
+ std::string out;
+ EXPECT_TRUE(dict.GetString(path, &out));
+ return out;
+}
+
+bool GetBoolean(const base::DictionaryValue& dict, base::StringPiece path) {
+ bool out = false;
+ EXPECT_TRUE(dict.GetBoolean(path, &out));
+ return out;
+}
+
+bool CheckHeader(const base::DictionaryValue& dict,
+ base::StringPiece header_name,
+ base::StringPiece header_value) {
+ const base::ListValue* headers = nullptr;
+ EXPECT_TRUE(dict.GetList("headers", &headers));
+ for (size_t i = 0; i < headers->GetSize(); ++i) {
+ const base::ListValue* name_value_pair = nullptr;
+ EXPECT_TRUE(headers->GetList(i, &name_value_pair));
+ EXPECT_EQ(2u, name_value_pair->GetSize());
+ std::string name;
+ EXPECT_TRUE(name_value_pair->GetString(0, &name));
+ std::string value;
+ EXPECT_TRUE(name_value_pair->GetString(1, &value));
+ if (name == header_name && value == header_value)
+ return true;
+ }
+ return false;
+}
+
} // namespace
-class ServiceWorkerBrowserTest : public testing::WithParamInterface<bool>,
- public ContentBrowserTest {
+class ServiceWorkerBrowserTest
+ : public MojoServiceWorkerTestP<ContentBrowserTest> {
protected:
using self = ServiceWorkerBrowserTest;
- void SetUp() override {
- is_mojo_enabled_ = GetParam();
- if (is_mojo_enabled()) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kMojoServiceWorker);
- }
- ContentBrowserTest::SetUp();
- }
-
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->Start());
StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
@@ -378,7 +417,6 @@ class ServiceWorkerBrowserTest : public testing::WithParamInterface<bool>,
ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
ServiceWorkerContext* public_context() { return wrapper(); }
- bool is_mojo_enabled() const { return is_mojo_enabled_; }
void AssociateRendererProcessToPattern(const GURL& pattern) {
wrapper_->process_manager()->AddProcessReferenceToPattern(
@@ -387,7 +425,6 @@ class ServiceWorkerBrowserTest : public testing::WithParamInterface<bool>,
private:
scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
- bool is_mojo_enabled_ = false;
};
class ConsoleListener : public EmbeddedWorkerInstance::Listener {
@@ -1361,6 +1398,744 @@ IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, Reload) {
run_loop.Run();
}
+class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
+ public:
+ using self = ServiceWorkerNavigationPreloadTest;
+
+ ~ServiceWorkerNavigationPreloadTest() override {}
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ 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;
+ static const std::string kPreloadResponseTestScript;
+
+ static bool HasNavigationPreloadHeader(
+ const net::test_server::HttpRequest& request) {
+ return request.headers.find(kNavigationPreloadHeaderName) !=
+ request.headers.end();
+ }
+
+ static std::string GetNavigationPreloadHeader(
+ const net::test_server::HttpRequest& request) {
+ DCHECK(HasNavigationPreloadHeader(request));
+ return request.headers.find(kNavigationPreloadHeaderName)->second;
+ }
+
+ void SetupForNavigationPreloadTest(const GURL& scope,
+ const GURL& worker_url) {
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ scope, worker_url,
+ base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
+ observer->Wait();
+
+ embedded_test_server()->RegisterRequestMonitor(
+ base::Bind(&self::MonitorRequestHandler, base::Unretained(this)));
+ }
+
+ void RegisterStaticFile(const std::string& relative_url,
+ const std::string& content,
+ const std::string& content_type) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&self::StaticRequestHandler, base::Unretained(this),
+ relative_url, content, content_type));
+ }
+
+ void RegisterCustomResponse(const std::string& relative_url,
+ const std::string& response) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&self::CustomRequestHandler, base::Unretained(this),
+ relative_url, response));
+ }
+
+ void RegisterKeepSearchRedirect(const std::string& relative_url,
+ const std::string& redirect_location) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&self::KeepSearchRedirectHandler, base::Unretained(this),
+ relative_url, redirect_location));
+ }
+
+ int GetRequestCount(const std::string& relative_url) const {
+ const auto& it = request_log_.find(relative_url);
+ if (it == request_log_.end())
+ return 0;
+ return it->second.size();
+ }
+
+ std::string GetTextContent() {
+ base::RunLoop run_loop;
+ std::string text_content;
+ shell()->web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
+ base::ASCIIToUTF16("document.body.textContent;"),
+ base::Bind(&StoreString, &text_content, run_loop.QuitClosure()));
+ run_loop.Run();
+ return text_content;
+ }
+
+ std::map<std::string, std::vector<net::test_server::HttpRequest>>
+ request_log_;
+
+ private:
+ class CustomResponse : public net::test_server::HttpResponse {
+ public:
+ CustomResponse(const std::string& response) : response_(response) {}
+ ~CustomResponse() override {}
+
+ void SendResponse(
+ const net::test_server::SendBytesCallback& send,
+ const net::test_server::SendCompleteCallback& done) override {
+ send.Run(response_, done);
+ }
+
+ private:
+ const std::string response_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomResponse);
+ };
+
+ std::unique_ptr<net::test_server::HttpResponse> StaticRequestHandler(
+ const std::string& relative_url,
+ const std::string& content,
+ const std::string& content_type,
+ const net::test_server::HttpRequest& request) const {
+ const size_t query_position = request.relative_url.find('?');
+ if (request.relative_url.substr(0, query_position) != relative_url)
+ return std::unique_ptr<net::test_server::HttpResponse>();
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
+ base::MakeUnique<net::test_server::BasicHttpResponse>());
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content(content);
+ http_response->set_content_type(content_type);
+ return std::move(http_response);
+ }
+
+ std::unique_ptr<net::test_server::HttpResponse> CustomRequestHandler(
+ const std::string& relative_url,
+ const std::string& response,
+ const net::test_server::HttpRequest& request) const {
+ const size_t query_position = request.relative_url.find('?');
+ if (request.relative_url.substr(0, query_position) != relative_url)
+ return std::unique_ptr<net::test_server::HttpResponse>();
+ return base::MakeUnique<CustomResponse>(response);
+ }
+
+ std::unique_ptr<net::test_server::HttpResponse> KeepSearchRedirectHandler(
+ const std::string& relative_url,
+ const std::string& redirect_location,
+ const net::test_server::HttpRequest& request) const {
+ const size_t query_position = request.relative_url.find('?');
+ if (request.relative_url.substr(0, query_position) != relative_url)
+ return std::unique_ptr<net::test_server::HttpResponse>();
+ std::unique_ptr<net::test_server::BasicHttpResponse> response(
+ new net::test_server::BasicHttpResponse());
+ response->set_code(net::HTTP_PERMANENT_REDIRECT);
+ response->AddCustomHeader(
+ "Location",
+ query_position == std::string::npos
+ ? redirect_location
+ : redirect_location + request.relative_url.substr(query_position));
+ return std::move(response);
+ }
+
+ void MonitorRequestHandler(const net::test_server::HttpRequest& request) {
+ request_log_[request.relative_url].push_back(request);
+ }
+};
+
+const std::string
+ ServiceWorkerNavigationPreloadTest::kNavigationPreloadHeaderName(
+ "Service-Worker-Navigation-Preload");
+
+const std::string
+ ServiceWorkerNavigationPreloadTest::kEnableNavigationPreloadScript(
+ "self.addEventListener('install', event => {\n"
+ " event.waitUntil(self.registration.navigationPreload.enable());\n"
+ " });\n");
+
+const std::string
+ ServiceWorkerNavigationPreloadTest::kPreloadResponseTestScript =
+ "var preload_resolve;\n"
+ "var preload_promise = new Promise(r => { preload_resolve = r; });\n"
+ "self.addEventListener('fetch', event => {\n"
+ " event.waitUntil(event.preloadResponse.then(\n"
+ " r => {\n"
+ " if (!r) {\n"
+ " preload_resolve(\n"
+ " {result: 'RESOLVED', \n"
+ " info: 'Resolved with ' + r + '.'});\n"
+ " return;\n"
+ " }\n"
+ " var info = {};\n"
+ " info.type = r.type;\n"
+ " info.url = r.url;\n"
+ " info.status = r.status;\n"
+ " info.ok = r.ok;\n"
+ " info.statusText = r.statusText;\n"
+ " info.headers = [];\n"
+ " r.headers.forEach(\n"
+ " (v, n) => { info.headers.push([n,v]); });\n"
+ " preload_resolve({result: 'RESOLVED',\n"
+ " info: JSON.stringify(info)}); },\n"
+ " e => { preload_resolve({result: 'REJECTED',\n"
+ " info: e.toString()}); }));\n"
+ " event.respondWith(\n"
+ " new Response(\n"
+ " '<title>WAITING</title><script>\\n' +\n"
+ " 'navigator.serviceWorker.onmessage = e => {\\n' +\n"
+ " ' var div = document.createElement(\\'div\\');\\n' +\n"
+ " ' div.appendChild(' +\n"
+ " ' document.createTextNode(e.data.info));\\n' +\n"
+ " ' document.body.appendChild(div);\\n' +\n"
+ " ' document.title = e.data.result;\\n' +\n"
+ " ' };\\n' +\n"
+ " 'navigator.serviceWorker.controller.postMessage(\\n' +\n"
+ " ' null);\\n' +\n"
+ " '</script>',"
+ " {headers: [['content-type', 'text/html']]}));\n"
+ " });\n"
+ "self.addEventListener('message', event => {\n"
+ " event.waitUntil(\n"
+ " preload_promise.then(\n"
+ " result => event.source.postMessage(result)));\n"
+ " });";
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>PASS</title>Hello world.";
+ const std::string kScript = kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " // Do nothing.\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("PASS");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ("Hello world.", GetTextContent());
+
+ // The page request must be sent once or twice:
+ // - A navigation preload request may be sent. But it is possible that the
+ // navigation preload request is canceled before reaching the server.
+ // - A fallback request must be sent since respondWith wasn't used.
+ const int request_count = GetRequestCount(kPageUrl);
+ ASSERT_TRUE(request_count == 1 || request_count == 2);
+ if (request_count == 1) {
+ // Fallback request.
+ EXPECT_FALSE(HasNavigationPreloadHeader(request_log_[kPageUrl][0]));
+ } else if (request_count == 2) {
+ // Navigation preload request.
+ ASSERT_TRUE(HasNavigationPreloadHeader(request_log_[kPageUrl][0]));
+ EXPECT_EQ("true", GetNavigationPreloadHeader(request_log_[kPageUrl][0]));
+ // Fallback request.
+ EXPECT_FALSE(HasNavigationPreloadHeader(request_log_[kPageUrl][1]));
+ }
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
+ const std::string kPageUrl = "/service_worker/navigation_preload.html";
+ const std::string kWorkerUrl = "/service_worker/navigation_preload.js";
+ const std::string kPage = "<title>FROM_SERVER</title>";
+ const std::string kScript =
+ "function createResponse(title, body) {\n"
+ " return new Response('<title>' + title + '</title>' + body,\n"
+ " {headers: [['content-type', 'text/html']]})\n"
+ "}\n"
+ "self.addEventListener('fetch', event => {\n"
+ " if (event.request.url.indexOf('?enable') != -1) {\n"
+ " event.respondWith(\n"
+ " self.registration.navigationPreload.enable()\n"
+ " .then(_ => event.preloadResponse)\n"
+ " .then(res => createResponse('ENABLED', res)));\n"
+ " } else if (event.request.url.indexOf('?change') != -1) {\n"
+ " event.respondWith(\n"
+ " self.registration.navigationPreload.setHeaderValue('Hello')\n"
+ " .then(_ => event.preloadResponse)\n"
+ " .then(res => createResponse('CHANGED', res)));\n"
+ " } else if (event.request.url.indexOf('?disable') != -1) {\n"
+ " event.respondWith(\n"
+ " self.registration.navigationPreload.disable()\n"
+ " .then(_ => event.preloadResponse)\n"
+ " .then(res => createResponse('DISABLED', res)));\n"
+ " } else if (event.request.url.indexOf('?test') != -1) {\n"
+ " event.respondWith(event.preloadResponse.then(res =>\n"
+ " createResponse('TEST', res)));\n"
+ " }\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const std::string kPageUrl1 = kPageUrl + "?enable";
+ const base::string16 title1 = base::ASCIIToUTF16("ENABLED");
+ TitleWatcher title_watcher1(shell()->web_contents(), title1);
+ title_watcher1.AlsoWaitForTitle(base::ASCIIToUTF16("FROM_SERVER"));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl1));
+ EXPECT_EQ(title1, title_watcher1.WaitAndGetTitle());
+ // When the navigation started, the navigation preload was not enabled yet.
+ EXPECT_EQ("null", GetTextContent());
+ ASSERT_EQ(0, GetRequestCount(kPageUrl1));
+
+ const std::string kPageUrl2 = kPageUrl + "?change";
+ const base::string16 title2 = base::ASCIIToUTF16("CHANGED");
+ TitleWatcher title_watcher2(shell()->web_contents(), title2);
+ title_watcher2.AlsoWaitForTitle(base::ASCIIToUTF16("FROM_SERVER"));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl2));
+ EXPECT_EQ(title2, title_watcher2.WaitAndGetTitle());
+ // When the navigation started, the navigation preload was enabled, but the
+ // header was not changed yet.
+ EXPECT_EQ("[object Response]", GetTextContent());
+ ASSERT_EQ(1, GetRequestCount(kPageUrl2));
+ ASSERT_TRUE(HasNavigationPreloadHeader(request_log_[kPageUrl2][0]));
+ EXPECT_EQ("true", GetNavigationPreloadHeader(request_log_[kPageUrl2][0]));
+
+ const std::string kPageUrl3 = kPageUrl + "?disable";
+ const base::string16 title3 = base::ASCIIToUTF16("DISABLED");
+ TitleWatcher title_watcher3(shell()->web_contents(), title3);
+ title_watcher3.AlsoWaitForTitle(base::ASCIIToUTF16("FROM_SERVER"));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl3));
+ EXPECT_EQ(title3, title_watcher3.WaitAndGetTitle());
+ // When the navigation started, the navigation preload was not disabled yet.
+ EXPECT_EQ("[object Response]", GetTextContent());
+ ASSERT_EQ(1, GetRequestCount(kPageUrl3));
+ ASSERT_TRUE(HasNavigationPreloadHeader(request_log_[kPageUrl3][0]));
+ EXPECT_EQ("Hello", GetNavigationPreloadHeader(request_log_[kPageUrl3][0]));
+
+ const std::string kPageUrl4 = kPageUrl + "?test";
+ const base::string16 title4 = base::ASCIIToUTF16("TEST");
+ TitleWatcher title_watcher4(shell()->web_contents(), title4);
+ title_watcher4.AlsoWaitForTitle(base::ASCIIToUTF16("FROM_SERVER"));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl4));
+ EXPECT_EQ(title4, title_watcher4.WaitAndGetTitle());
+ // When the navigation started, the navigation preload must be disabled.
+ EXPECT_EQ("null", GetTextContent());
+ ASSERT_EQ(0, GetRequestCount(kPageUrl4));
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ RespondWithNavigationPreload) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>PASS</title>Hello world.";
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " if (!event.preloadResponse) {\n"
+ " event.respondWith(\n"
+ " new Response('<title>ERROR</title>',"
+ " {headers: [['content-type', 'text/html']]}));\n"
+ " return;\n"
+ " }\n"
+ " event.respondWith(event.preloadResponse);\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("PASS");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ("Hello world.", GetTextContent());
+
+ // The page request must be sent only once, since the worker responded with
+ // the navigation preload response
+ ASSERT_EQ(1, GetRequestCount(kPageUrl));
+ EXPECT_EQ("true",
+ request_log_[kPageUrl][0].headers[kNavigationPreloadHeaderName]);
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, GetResponseText) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>PASS</title>Hello world.";
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " event.respondWith(\n"
+ " event.preloadResponse\n"
+ " .then(response => response.text())\n"
+ " .then(text =>\n"
+ " new Response(\n"
+ " text,\n"
+ " {headers: [['content-type', 'text/html']]})));\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("PASS");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ("Hello world.", GetTextContent());
+
+ // The page request must be sent only once, since the worker responded with
+ // "Hello world".
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ AbortPreloadRequest) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>ERROR</title>Hello world.";
+ // In this script, event.preloadResponse is not guarded by event.waitUntil.
+ // So the preload request should be canceled, when the fetch event handler
+ // has been executed.
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "var preload_resolve;\n"
+ "var preload_promise = new Promise(r => { preload_resolve = r; });\n"
+ "self.addEventListener('fetch', event => {\n"
+ " event.preloadResponse.then(\n"
+ " _ => { preload_resolve({result: 'RESOLVED',\n"
+ " info: 'Preload resolved.'}); },\n"
+ " e => { preload_resolve({result: 'REJECTED',\n"
+ " info: e.toString()}); });\n"
+ " event.respondWith(\n"
+ " new Response(\n"
+ " '<title>WAITING</title><script>\\n' +\n"
+ " 'navigator.serviceWorker.onmessage = e => {\\n' +\n"
+ " ' var div = document.createElement(\\'div\\');\\n' +\n"
+ " ' div.appendChild(' +\n"
+ " ' document.createTextNode(e.data.info));\\n' +\n"
+ " ' document.body.appendChild(div);\\n' +\n"
+ " ' document.title = e.data.result;\\n' +\n"
+ " ' };\\n' +\n"
+ " 'navigator.serviceWorker.controller.postMessage(\\n' +\n"
+ " ' null);\\n' +\n"
+ " '</script>',"
+ " {headers: [['content-type', 'text/html']]}));\n"
+ " });\n"
+ "self.addEventListener('message', event => {\n"
+ " event.waitUntil(\n"
+ " preload_promise.then(\n"
+ " result => event.source.postMessage(result)));\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("REJECTED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ EXPECT_EQ(
+ "AbortError: Service Worker navigation preload aborted. Need to guard "
+ "with respondWith or waitUntil.",
+ GetTextContent());
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkError) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(
+ kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
+ "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ const base::string16 title = base::ASCIIToUTF16("REJECTED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ("NetworkError: Service Worker navigation preload network error.",
+ GetTextContent());
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ PreloadHeadersSimple) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>ERROR</title>Hello world.";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(
+ kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
+ "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("RESOLVED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page request must be sent only once, since the worker responded with
+ // a generated Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+ std::unique_ptr<base::Value> result =
+ base::JSONReader::Read(GetTextContent());
+ base::DictionaryValue* dict = nullptr;
+ ASSERT_TRUE(result->GetAsDictionary(&dict));
+ EXPECT_EQ("basic", GetString(*dict, "type"));
+ EXPECT_EQ(page_url, GURL(GetString(*dict, "url")));
+ EXPECT_EQ(200, GetInt(*dict, "status"));
+ EXPECT_EQ(true, GetBoolean(*dict, "ok"));
+ EXPECT_EQ("OK", GetString(*dict, "statusText"));
+ EXPECT_TRUE(CheckHeader(*dict, "content-type", "text/html"));
+ EXPECT_TRUE(CheckHeader(*dict, "content-length",
+ base::IntToString(sizeof(kPage) - 1)));
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NotEnabled) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>ERROR</title>Hello world.";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kPreloadResponseTestScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("RESOLVED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page request must not be sent, since the worker responded with a
+ // generated Response and the navigation preload isn't enabled.
+ EXPECT_EQ(0, GetRequestCount(kPageUrl));
+ EXPECT_EQ("Resolved with null.", GetTextContent());
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ PreloadHeadersCustom) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPageResponse[] =
+ "HTTP/1.1 201 HELLOWORLD\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 32\r\n"
+ "Content-Type: text/html\r\n"
+ "Custom-Header: pen pineapple\r\n"
+ "Custom-Header: apple pen\r\n"
+ "Set-Cookie: COOKIE1\r\n"
+ "Set-Cookie2: COOKIE2\r\n"
+ "\r\n"
+ "<title>ERROR</title>Hello world.";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterCustomResponse(kPageUrl, kPageResponse);
+ RegisterStaticFile(
+ kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
+ "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("RESOLVED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page request must be sent only once, since the worker responded with
+ // a generated Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+ std::unique_ptr<base::Value> result =
+ base::JSONReader::Read(GetTextContent());
+ base::DictionaryValue* dict = nullptr;
+ ASSERT_TRUE(result->GetAsDictionary(&dict));
+ EXPECT_EQ("basic", GetString(*dict, "type"));
+ EXPECT_EQ(page_url, GURL(GetString(*dict, "url")));
+ EXPECT_EQ(201, GetInt(*dict, "status"));
+ EXPECT_EQ(true, GetBoolean(*dict, "ok"));
+ EXPECT_EQ("HELLOWORLD", GetString(*dict, "statusText"));
+ EXPECT_TRUE(CheckHeader(*dict, "content-type", "text/html"));
+ EXPECT_TRUE(CheckHeader(*dict, "content-length", "32"));
+ EXPECT_TRUE(CheckHeader(*dict, "custom-header", "pen pineapple, apple pen"));
+ // The forbidden response headers (Set-Cookie, Set-Cookie2) must be removed.
+ EXPECT_FALSE(dict->HasKey("set-cookie"));
+ EXPECT_FALSE(dict->HasKey("set-cookie2"));
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kRedirectedPageUrl[] =
+ "/service_worker/navigation_preload_redirected.html";
+ const char kPageResponse[] =
+ "HTTP/1.1 302 Found\r\n"
+ "Connection: close\r\n"
+ "Location: /service_worker/navigation_preload_redirected.html\r\n"
+ "\r\n";
+ const char kRedirectedPage[] = "<title>ERROR</title>Redirected page.";
+ const GURL redirecred_page_url =
+ embedded_test_server()->GetURL(kRedirectedPageUrl);
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterCustomResponse(kPageUrl, kPageResponse);
+ RegisterStaticFile(
+ kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
+ "text/javascript");
+ RegisterStaticFile(kRedirectedPageUrl, kRedirectedPage, "text/html");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("REJECTED");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page request must be sent only once, since the worker responded with
+ // a generated Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+ // The redirected request must not be sent.
+ EXPECT_EQ(0, GetRequestCount(kRedirectedPageUrl));
+ EXPECT_EQ(
+ "NetworkError: Service Worker navigation preload doesn't suport "
+ "redirect.",
+ GetTextContent());
+}
+
+// Tests responding with the navigation preload response when the navigation
+// occurred after a redirect.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ RedirectAndRespondWithNavigationPreload) {
+ const std::string kPageUrl = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] =
+ "<title></title>\n"
+ "<script>document.title = document.location.search;</script>";
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " if (event.request.url.indexOf('navigation_preload.html') == -1)\n"
+ " return; // For in scope redirection.\n"
+ " event.respondWith(event.preloadResponse);\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, kPage, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ // Register redirects to the target URL. The service worker responds to the
+ // target URL with the navigation preload response.
+ const char kRedirectPageUrl[] = "/redirect";
+ const char kInScopeRedirectPageUrl[] = "/service_worker/redirect";
+ RegisterKeepSearchRedirect(kRedirectPageUrl, page_url.spec());
+ RegisterKeepSearchRedirect(kInScopeRedirectPageUrl, page_url.spec());
+
+ SetupForNavigationPreloadTest(
+ embedded_test_server()->GetURL("/service_worker/"), worker_url);
+
+ const GURL redirect_page_url =
+ embedded_test_server()->GetURL(kRedirectPageUrl).Resolve("?1");
+ const GURL in_scope_redirect_page_url =
+ embedded_test_server()->GetURL(kInScopeRedirectPageUrl).Resolve("?2");
+ const GURL cross_origin_redirect_page_url =
+ embedded_test_server()->GetURL("a.com", kRedirectPageUrl).Resolve("?3");
+
+ // Navigate to a same-origin, out of scope URL that redirects to the target
+ // URL. The navigation preload request should be the single request to the
+ // target URL.
+ const base::string16 title1 = base::ASCIIToUTF16("?1");
+ TitleWatcher title_watcher1(shell()->web_contents(), title1);
+ NavigateToURL(shell(), redirect_page_url);
+ EXPECT_EQ(title1, title_watcher1.WaitAndGetTitle());
+ EXPECT_EQ(1, GetRequestCount(kPageUrl + "?1"));
+
+ // Navigate to a same-origin, in-scope URL that redirects to the target URL.
+ // The navigation preload request should be the single request to the target
+ // URL.
+ const base::string16 title2 = base::ASCIIToUTF16("?2");
+ TitleWatcher title_watcher2(shell()->web_contents(), title2);
+ NavigateToURL(shell(), in_scope_redirect_page_url);
+ EXPECT_EQ(title2, title_watcher2.WaitAndGetTitle());
+ EXPECT_EQ(1, GetRequestCount(kPageUrl + "?2"));
+
+ // Navigate to a cross-origin URL that redirects to the target URL. The
+ // navigation preload request should be the single request to the target URL.
+ const base::string16 title3 = base::ASCIIToUTF16("?3");
+ TitleWatcher title_watcher3(shell()->web_contents(), title3);
+ NavigateToURL(shell(), cross_origin_redirect_page_url);
+ EXPECT_EQ(title3, title_watcher3.WaitAndGetTitle());
+ EXPECT_EQ(1, GetRequestCount(kPageUrl + "?3"));
+}
+
+// When the content type of the page is not correctly set,
+// OnStartLoadingResponseBody() of mojom::URLLoaderClient is called before
+// OnReceiveResponse(). This behavior is caused by MimeSniffingResourceHandler.
+// This test checks that even if the MimeSniffingResourceHandler is triggered
+// navigation preload must be handled correctly.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+ RespondWithNavigationPreloadWithMimeSniffing) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ const char kPage[] = "<title>PASS</title>Hello world.";
+ const std::string kScript = kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " event.respondWith(event.preloadResponse);\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+
+ // Setting an empty content type to trigger MimeSniffingResourceHandler.
+ RegisterStaticFile(kPageUrl, kPage, "");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ SetupForNavigationPreloadTest(page_url, worker_url);
+
+ const base::string16 title = base::ASCIIToUTF16("PASS");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), page_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ("Hello world.", GetTextContent());
+
+ // The page request must be sent only once, since the worker responded with
+ // the navigation preload response
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
// Flaky on Win/Mac: http://crbug.com/533631
#if defined(OS_WIN) || defined(OS_MACOSX)
#define MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure DISABLED_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
@@ -1388,11 +2163,14 @@ IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), https_server.GetURL(kPageUrl));
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
- EXPECT_FALSE(static_cast<WebContentsImpl*>(shell()->web_contents())
- ->DisplayedInsecureContent());
NavigationEntry* entry =
shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, entry->GetSSL().security_style);
+ EXPECT_TRUE(entry->GetSSL().initialized);
+ EXPECT_FALSE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
+ EXPECT_TRUE(
+ https_server.GetCertificate()->Equals(entry->GetSSL().certificate.get()));
+ EXPECT_EQ(0u, entry->GetSSL().cert_status);
shell()->Close();
@@ -1420,11 +2198,12 @@ IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
- EXPECT_FALSE(static_cast<WebContentsImpl*>(shell()->web_contents())
- ->DisplayedInsecureContent());
NavigationEntry* entry =
shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, entry->GetSSL().security_style);
+ EXPECT_TRUE(entry->GetSSL().initialized);
+ EXPECT_FALSE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
+ EXPECT_FALSE(entry->GetSSL().certificate);
shell()->Close();
@@ -2056,6 +2835,9 @@ INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
ServiceWorkerBlackBoxBrowserTest,
::testing::Values(true, false));
INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+ ServiceWorkerNavigationPreloadTest,
+ ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
ServiceWorkerV8CacheStrategiesTest,
::testing::Values(true, false));
INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer.h b/chromium/content/browser/service_worker/service_worker_cache_writer.h
index e32c24dfea5..0e3bd7094f1 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.h
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.h
@@ -20,10 +20,8 @@
namespace content {
struct HttpResponseInfoIOBuffer;
-class ServiceWorkerCacheWriterCore;
class ServiceWorkerResponseReader;
class ServiceWorkerResponseWriter;
-class ServiceWorkerStorage;
// This class is responsible for possibly updating the ServiceWorker script
// cache for an installed ServiceWorker main script. If there is no existing
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
index d6f3730695a..2a9b464eaa4 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -399,13 +400,16 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheWriterTest);
};
+class ServiceWorkerCacheWriterTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerCacheWriterTest> {};
+
// Passthrough tests:
// In these tests, the ServiceWorkerCacheWriter under test has no existing
// reader, since no calls to ExpectReader() have been made; this means that
// there is no existing cached response and the incoming data is written back to
// the cache directly.
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersSync) {
const size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(kHeaderSize, false);
@@ -418,7 +422,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersAsync) {
size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(kHeaderSize, true);
@@ -434,7 +438,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataSync) {
const std::string data1 = "abcdef";
const std::string data2 = "ghijklmno";
size_t response_size = data1.size() + data2.size();
@@ -456,7 +460,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) {
EXPECT_TRUE(writer->AllExpectedWritesDone());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataAsync) {
const std::string data1 = "abcdef";
const std::string data2 = "ghijklmno";
size_t response_size = data1.size() + data2.size();
@@ -484,7 +488,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) {
EXPECT_TRUE(writer->AllExpectedWritesDone());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersFailSync) {
const size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfo(kHeaderSize, false, net::ERR_FAILED);
@@ -497,7 +501,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailSync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersFailAsync) {
size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfo(kHeaderSize, true, net::ERR_FAILED);
@@ -513,7 +517,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailAsync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataFailSync) {
const std::string data = "abcdef";
MockServiceWorkerResponseWriter* writer = ExpectWriter();
@@ -526,7 +530,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailSync) {
EXPECT_TRUE(writer->AllExpectedWritesDone());
}
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataFailAsync) {
const std::string data = "abcdef";
MockServiceWorkerResponseWriter* writer = ExpectWriter();
@@ -548,7 +552,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailAsync) {
// reader for an existing cached response, so it will compare the response being
// written to it against the existing cached response.
-TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareHeadersSync) {
size_t response_size = 3;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
MockServiceWorkerResponseReader* reader = ExpectReader();
@@ -562,7 +566,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) {
EXPECT_TRUE(reader->AllExpectedReadsDone());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareDataOkSync) {
const std::string data1 = "abcdef";
size_t response_size = data1.size();
@@ -584,7 +588,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersFailSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareHeadersFailSync) {
size_t response_size = 3;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
MockServiceWorkerResponseReader* reader = ExpectReader();
@@ -597,7 +601,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersFailSync) {
EXPECT_TRUE(reader->AllExpectedReadsDone());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataFailSync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareDataFailSync) {
const std::string data1 = "abcdef";
size_t response_size = data1.size();
@@ -618,7 +622,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataFailSync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareShortCacheReads) {
const size_t kHeaderSize = 16;
const std::string& data1 = "abcdef";
const std::string& cache_data2 = "ghi";
@@ -648,7 +652,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareDataOkAsync) {
const std::string data1 = "abcdef";
size_t response_size = data1.size();
@@ -670,7 +674,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) {
EXPECT_EQ(0U, cache_writer_->bytes_written());
}
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareDataManyOkAsync) {
const std::string expected_data[] = {
"abcdef", "ghijkl", "mnopqr", "stuvwxyz",
};
@@ -705,7 +709,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) {
// differs in the cached version. The writer should be asked to rewrite the
// headers and body with the new value, and the copy reader should be asked to
// read the header and data1.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopySync) {
std::string data1 = "abcdef";
std::string cache_data2 = "ghijkl";
std::string net_data2 = "mnopqr";
@@ -746,7 +750,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) {
}
// Tests behavior when the cached data is shorter than the network data.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopyShort) {
std::string data1 = "abcdef";
std::string cache_data2 = "mnop";
std::string net_data2 = "mnopqr";
@@ -788,7 +792,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) {
}
// Tests behavior when the cached data is longer than the network data.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
+TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopyLong) {
std::string data1 = "abcdef";
std::string cache_data2 = "mnop";
std::string net_data2 = "mnop";
@@ -831,5 +835,9 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheWriterTest,
+ ServiceWorkerCacheWriterTestP,
+ testing::Bool());
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_client_utils.cc b/chromium/content/browser/service_worker/service_worker_client_utils.cc
index 0cd39b270e3..dbd59d7f0a5 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -162,6 +162,13 @@ void DidOpenURLOnUI(const OpenURLCallback& callback,
return;
}
+ // ContentBrowserClient::OpenURL calls ui::BaseWindow::Show which
+ // makes the destination window the main+key window, but won't make Chrome
+ // the active application (https://crbug.com/470830). Since OpenWindow is
+ // always called from a user gesture (e.g. notification click), we should
+ // explicitly activate the window, which brings Chrome to the front.
+ static_cast<WebContentsImpl*>(web_contents)->Activate();
+
RenderFrameHostImpl* rfhi =
static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
new OpenURLObserver(web_contents,
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 18ddd2d7eb3..2c8bfbe727c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -30,7 +30,6 @@ class GURL;
namespace base {
class FilePath;
-class SequencedTaskRunner;
class SingleThreadTaskRunner;
}
@@ -293,8 +292,8 @@ class CONTENT_EXPORT ServiceWorkerContextCore
}
private:
- friend class ServiceWorkerContextCoreTest;
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextCoreTest, FailureInfo);
+ friend class ServiceWorkerContextCoreTestP;
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextCoreTestP, FailureInfo);
typedef std::map<int64_t, ServiceWorkerRegistration*> RegistrationsMap;
typedef std::map<int64_t, ServiceWorkerVersion*> VersionMap;
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
index d5b50705de2..e0e5c69f04c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +34,10 @@ class ServiceWorkerContextCoreTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCoreTest);
};
-TEST_F(ServiceWorkerContextCoreTest, FailureInfo) {
+class ServiceWorkerContextCoreTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerContextCoreTest> {};
+
+TEST_P(ServiceWorkerContextCoreTestP, FailureInfo) {
const int64_t kVersionId = 55; // dummy value
EXPECT_EQ(0, context()->GetVersionFailureCount(kVersionId));
@@ -58,4 +62,8 @@ TEST_F(ServiceWorkerContextCoreTest, FailureInfo) {
EXPECT_FALSE(base::ContainsKey(context()->failure_counts_, kVersionId));
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerContextCoreTest,
+ ServiceWorkerContextCoreTestP,
+ testing::Bool());
+
} // namespace content
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 dbc170cf418..912210fa583 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
@@ -15,6 +15,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_test_utils.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_request_info.h"
@@ -82,7 +83,10 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
GURL script_url_;
};
-TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateBefore24Hours) {
+class ServiceWorkerContextRequestHandlerTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerContextRequestHandlerTest> {};
+
+TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateBefore24Hours) {
// Give the registration a very recent last update time and pretend
// we're installing a new version.
registration_->set_last_update_check(base::Time::Now());
@@ -108,7 +112,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateBefore24Hours) {
EXPECT_FALSE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
}
-TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateAfter24Hours) {
+TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateAfter24Hours) {
// Give the registration a old update time and pretend
// we're installing a new version.
registration_->set_last_update_check(
@@ -135,7 +139,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateAfter24Hours) {
EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
}
-TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache) {
+TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateForceBypassCache) {
// Give the registration a very recent last update time and pretend
// we're installing a new version.
registration_->set_last_update_check(base::Time::Now());
@@ -162,7 +166,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache) {
EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
}
-TEST_F(ServiceWorkerContextRequestHandlerTest,
+TEST_P(ServiceWorkerContextRequestHandlerTestP,
ServiceWorkerDataRequestAnnotation) {
version_->SetStatus(ServiceWorkerVersion::NEW);
provider_host_->running_hosted_version_ = version_;
@@ -188,4 +192,8 @@ TEST_F(ServiceWorkerContextRequestHandlerTest,
sw_job->net_request_.get()));
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRequestHandlerTest,
+ ServiceWorkerContextRequestHandlerTestP,
+ testing::Bool());
+
} // namespace content
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 6c72fab2cab..d25da543994 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -20,6 +20,7 @@
#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_storage.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/public/test/test_browser_thread_bundle.h"
@@ -161,11 +162,54 @@ class ServiceWorkerContextTest : public ServiceWorkerContextObserver,
std::vector<NotificationLog> notifications_;
};
+class ServiceWorkerContextTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerContextTest> {};
+
+class RecordableEmbeddedWorkerInstanceClient
+ : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient {
+ public:
+ enum class Message { StartWorker, StopWorker };
+
+ explicit RecordableEmbeddedWorkerInstanceClient(
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+ : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
+
+ const std::vector<Message>& events() const { return events_; }
+
+ protected:
+ void StartWorker(
+ const EmbeddedWorkerStartParams& params,
+ service_manager::mojom::InterfaceProviderPtr browser_interfaces,
+ service_manager::mojom::InterfaceProviderRequest renderer_request)
+ override {
+ events_.push_back(Message::StartWorker);
+ EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
+ params, std::move(browser_interfaces), std::move(renderer_request));
+ }
+
+ void StopWorker(const StopWorkerCallback& callback) override {
+ events_.push_back(Message::StopWorker);
+ EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker(
+ std::move(callback));
+ }
+
+ std::vector<Message> events_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RecordableEmbeddedWorkerInstanceClient);
+};
+
// Make sure basic registration is working.
-TEST_F(ServiceWorkerContextTest, Register) {
+TEST_P(ServiceWorkerContextTestP, Register) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
+ RecordableEmbeddedWorkerInstanceClient* client = nullptr;
+ if (is_mojo_enabled()) {
+ client = helper_->CreateAndRegisterMockInstanceClient<
+ RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
+ }
+
int64_t registration_id = kInvalidServiceWorkerRegistrationId;
bool called = false;
context()->RegisterServiceWorker(
@@ -178,15 +222,28 @@ TEST_F(ServiceWorkerContextTest, Register) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StartWorker::ID));
- EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_InstallEvent::ID));
- EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ActivateEvent::ID));
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StopWorker::ID));
+ if (is_mojo_enabled()) {
+ EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
+ ASSERT_EQ(2UL, client->events().size());
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+ client->events()[0]);
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+ client->events()[1]);
+ } else {
+ EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
+ }
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
ASSERT_EQ(1u, notifications_.size());
@@ -207,13 +264,20 @@ TEST_F(ServiceWorkerContextTest, Register) {
// Test registration when the service worker rejects the install event. The
// registration callback should indicate success, but there should be no waiting
// or active worker in the registration.
-TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
+TEST_P(ServiceWorkerContextTestP, Register_RejectInstall) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
helper_.reset(); // Make sure the process lookups stay overridden.
helper_.reset(new RejectInstallTestHelper);
helper_->context_wrapper()->AddObserver(this);
+
+ RecordableEmbeddedWorkerInstanceClient* client = nullptr;
+ if (is_mojo_enabled()) {
+ client = helper_->CreateAndRegisterMockInstanceClient<
+ RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
+ }
+
int64_t registration_id = kInvalidServiceWorkerRegistrationId;
bool called = false;
context()->RegisterServiceWorker(
@@ -226,15 +290,28 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StartWorker::ID));
- EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_InstallEvent::ID));
- EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ActivateEvent::ID));
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StopWorker::ID));
+ if (is_mojo_enabled()) {
+ EXPECT_EQ(1UL, helper_->ipc_sink()->message_count());
+ ASSERT_EQ(2UL, client->events().size());
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+ client->events()[0]);
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+ client->events()[1]);
+ } else {
+ EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
+ }
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
ASSERT_EQ(1u, notifications_.size());
@@ -254,13 +331,20 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
// Test registration when the service worker rejects the activate event. The
// worker should be activated anyway.
-TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
+TEST_P(ServiceWorkerContextTestP, Register_RejectActivate) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
helper_.reset();
helper_.reset(new RejectActivateTestHelper);
helper_->context_wrapper()->AddObserver(this);
+
+ RecordableEmbeddedWorkerInstanceClient* client = nullptr;
+ if (is_mojo_enabled()) {
+ client = helper_->CreateAndRegisterMockInstanceClient<
+ RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
+ }
+
int64_t registration_id = kInvalidServiceWorkerRegistrationId;
bool called = false;
context()->RegisterServiceWorker(
@@ -271,15 +355,28 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StartWorker::ID));
- EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_InstallEvent::ID));
- EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ActivateEvent::ID));
- EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StopWorker::ID));
+ if (is_mojo_enabled()) {
+ EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
+ ASSERT_EQ(2UL, client->events().size());
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+ client->events()[0]);
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+ client->events()[1]);
+ } else {
+ EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
+ }
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
ASSERT_EQ(1u, notifications_.size());
@@ -295,7 +392,7 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
}
// Make sure registrations are cleaned up when they are unregistered.
-TEST_F(ServiceWorkerContextTest, Unregister) {
+TEST_P(ServiceWorkerContextTestP, Unregister) {
GURL pattern("http://www.example.com/");
bool called = false;
@@ -338,7 +435,7 @@ TEST_F(ServiceWorkerContextTest, Unregister) {
}
// Make sure registrations are cleaned up when they are unregistered in bulk.
-TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
+TEST_P(ServiceWorkerContextTestP, UnregisterMultiple) {
GURL origin1_p1("http://www.example.com/test");
GURL origin1_p2("http://www.example.com/hello");
GURL origin2_p1("http://www.example.com:8080/again");
@@ -441,7 +538,7 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
}
// Make sure registering a new script shares an existing registration.
-TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
+TEST_P(ServiceWorkerContextTestP, RegisterNewScript) {
GURL pattern("http://www.example.com/");
bool called = false;
@@ -483,7 +580,7 @@ TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
-TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
+TEST_P(ServiceWorkerContextTestP, RegisterDuplicateScript) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
@@ -522,7 +619,7 @@ TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
}
-TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
+TEST_P(ServiceWorkerContextTestP, ProviderHostIterator) {
const int kRenderProcessId1 = 1;
const int kRenderProcessId2 = 2;
const GURL kOrigin1 = GURL("http://www.example.com/");
@@ -606,22 +703,29 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
class ServiceWorkerContextRecoveryTest
: public ServiceWorkerContextTest,
- public testing::WithParamInterface<bool> {
+ public testing::WithParamInterface<testing::tuple<bool, bool>> {
public:
ServiceWorkerContextRecoveryTest() {}
virtual ~ServiceWorkerContextRecoveryTest() {}
-};
-INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
- ServiceWorkerContextRecoveryTest,
- testing::Values(true, false));
+ protected:
+ void SetUp() override {
+ if (!is_mojo_enabled()) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableMojoServiceWorker);
+ }
+ ServiceWorkerContextTest::SetUp();
+ }
+
+ bool is_mojo_enabled() const { return testing::get<0>(GetParam()); }
+ bool is_storage_on_disk() const { return testing::get<1>(GetParam()); }
+};
TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
- bool is_storage_on_disk = GetParam();
- if (is_storage_on_disk) {
+ if (is_storage_on_disk()) {
// Reinitialize the helper to test on-disk storage.
base::ScopedTempDir user_data_directory;
ASSERT_TRUE(user_data_directory.CreateUniqueTempDir());
@@ -709,5 +813,12 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
EXPECT_EQ(registration_id, notifications_[2].registration_id);
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerContextTest,
+ ServiceWorkerContextTestP,
+ testing::Bool());
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
+ ServiceWorkerContextRecoveryTest,
+ testing::Combine(testing::Bool(), testing::Bool()));
} // 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 eeac4d3bfa1..686e5ea57d8 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -22,6 +22,7 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/render_process_host_impl.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_observer.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
@@ -579,6 +580,32 @@ void ServiceWorkerContextWrapper::CheckHasServiceWorker(
callback));
}
+void ServiceWorkerContextWrapper::CountExternalRequestsForTest(
+ const GURL& origin,
+ const CountExternalRequestsCallback& callback) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::CountExternalRequestsForTest,
+ this, origin, callback));
+ return;
+ }
+
+ std::vector<ServiceWorkerVersionInfo> live_version_info =
+ GetAllLiveVersionInfo();
+ size_t pending_external_request_count = 0;
+ for (const ServiceWorkerVersionInfo& info : live_version_info) {
+ ServiceWorkerVersion* version = GetLiveVersion(info.version_id);
+ if (version && version->scope().GetOrigin() == origin) {
+ pending_external_request_count =
+ version->GetExternalRequestCountForTest();
+ break;
+ }
+ }
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, pending_external_request_count));
+}
+
void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
const base::Closure& callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
@@ -832,6 +859,28 @@ void ServiceWorkerContextWrapper::ShutdownOnIO() {
context_core_.reset();
}
+bool ServiceWorkerContextWrapper::StartingExternalRequest(
+ int64_t service_worker_version_id,
+ const std::string& request_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerVersion* version =
+ context()->GetLiveVersion(service_worker_version_id);
+ if (!version)
+ return false;
+ return version->StartExternalRequest(request_uuid);
+}
+
+bool ServiceWorkerContextWrapper::FinishedExternalRequest(
+ int64_t service_worker_version_id,
+ const std::string& request_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerVersion* version =
+ context()->GetLiveVersion(service_worker_version_id);
+ if (!version)
+ return false;
+ return version->FinishExternalRequest(request_uuid);
+}
+
void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
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 12c8b7220cd..125de792858 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -20,7 +20,6 @@
namespace base {
class FilePath;
-class SequencedTaskRunner;
class SingleThreadTaskRunner;
}
@@ -105,6 +104,9 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
const GURL& url,
const GURL& other_url,
const CheckHasServiceWorkerCallback& callback) override;
+ void CountExternalRequestsForTest(
+ const GURL& url,
+ const CountExternalRequestsCallback& callback) override;
void StopAllServiceWorkersForOrigin(const GURL& origin) override;
void ClearAllServiceWorkersForTest(const base::Closure& callback) override;
void StartServiceWorkerForNavigationHint(
@@ -112,6 +114,10 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
blink::WebNavigationHintType type,
int render_process_id,
const ResultCallback& callback) override;
+ bool StartingExternalRequest(int64_t service_worker_version_id,
+ const std::string& request_uuid) override;
+ bool FinishedExternalRequest(int64_t service_worker_version_id,
+ const std::string& request_uuid) override;
// These methods must only be called from the IO thread.
ServiceWorkerRegistration* GetLiveRegistration(int64_t registration_id);
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 4e94eb7f927..33ce346b44d 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,8 +17,10 @@
#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_test_utils.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/resource_request_body_impl.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/request_context_frame_type.h"
@@ -153,6 +155,10 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
GURL script_url_;
};
+class ServiceWorkerControlleeRequestHandlerTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerControlleeRequestHandlerTest> {
+};
+
class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
public:
ServiceWorkerTestContentBrowserClient() {}
@@ -165,7 +171,7 @@ class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
}
};
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTestP, DisallowServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
SetBrowserClientForTesting(&test_browser_client);
@@ -199,7 +205,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
SetBrowserClientForTesting(old_browser_client);
}
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTestP, ActivateWaitingVersion) {
// Store a registration that is installed but not activated yet.
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -234,7 +240,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
}
// Test that an installing registration is associated with a provider host.
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTestP, InstallingRegistration) {
// Create an installing registration.
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->set_fetch_handler_existence(
@@ -260,7 +266,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
}
// Test to not regress crbug/414118.
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTestP, DeletedProviderHost) {
// Store a registration so the call to FindRegistrationForDocument will read
// from the database.
version_->set_fetch_handler_existence(
@@ -293,7 +299,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
}
-TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
+TEST_P(ServiceWorkerControlleeRequestHandlerTestP, FallbackWithNoFetchHandler) {
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -343,4 +349,8 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
EXPECT_FALSE(sub_cors_job->ShouldForwardToServiceWorker());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerControlleeRequestHandlerTest,
+ ServiceWorkerControlleeRequestHandlerTestP,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index fed2adb34ad..e644d7fd902 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1223,6 +1223,16 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
}
out->foreign_fetch_origins.push_back(parsed_origin);
}
+ if (data.has_origin_trial_tokens()) {
+ const ServiceWorkerOriginTrialInfo& info = data.origin_trial_tokens();
+ TrialTokenValidator::FeatureToTokensMap origin_trial_tokens;
+ for (int i = 0; i < info.features_size(); ++i) {
+ const auto& feature = info.features(i);
+ for (int j = 0; j < feature.tokens_size(); ++j)
+ origin_trial_tokens[feature.name()].push_back(feature.tokens(j));
+ }
+ out->origin_trial_tokens = origin_trial_tokens;
+ }
return ServiceWorkerDatabase::STATUS_OK;
}
@@ -1256,6 +1266,15 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
}
for (const url::Origin& origin : registration.foreign_fetch_origins)
data.add_foreign_fetch_origin(origin.Serialize());
+ if (registration.origin_trial_tokens) {
+ ServiceWorkerOriginTrialInfo* info = data.mutable_origin_trial_tokens();
+ for (const auto& feature : *registration.origin_trial_tokens) {
+ ServiceWorkerOriginTrialFeature* feature_out = info->add_features();
+ feature_out->set_name(feature.first);
+ for (const auto& token : feature.second)
+ feature_out->add_tokens(token);
+ }
+ }
std::string value;
bool success = data.SerializeToString(&value);
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index 6141f012441..d3a622f6f9b 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -16,9 +16,11 @@
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/common/origin_trials/trial_token_validator.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -70,6 +72,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
base::Time last_update_check;
std::vector<GURL> foreign_fetch_scopes;
std::vector<url::Origin> foreign_fetch_origins;
+ base::Optional<TrialTokenValidator::FeatureToTokensMap> origin_trial_tokens;
// Not populated until ServiceWorkerStorage::StoreRegistration is called.
int64_t resources_total_size_bytes;
diff --git a/chromium/content/browser/service_worker/service_worker_database.proto b/chromium/content/browser/service_worker/service_worker_database.proto
index e85f2a7c830..6bb84561f14 100644
--- a/chromium/content/browser/service_worker/service_worker_database.proto
+++ b/chromium/content/browser/service_worker/service_worker_database.proto
@@ -8,6 +8,15 @@ option optimize_for = LITE_RUNTIME;
package content;
+message ServiceWorkerOriginTrialFeature {
+ required string name = 1;
+ repeated string tokens = 2;
+}
+
+message ServiceWorkerOriginTrialInfo {
+ repeated ServiceWorkerOriginTrialFeature features = 1;
+}
+
message ServiceWorkerRegistrationData {
required int64 registration_id = 1;
required string scope_url = 2;
@@ -28,6 +37,12 @@ message ServiceWorkerRegistrationData {
repeated string foreign_fetch_scope = 9;
repeated string foreign_fetch_origin = 10;
+
+ // If the registration data was created by old Chrome (< M56),
+ // |origin_trial_tokens| is not set. In this case, we have to start the
+ // Service Worker and load the main script resource in ServiceWorkerStorage
+ // to check the HTTP header.
+ optional ServiceWorkerOriginTrialInfo origin_trial_tokens = 11;
}
message ServiceWorkerResourceRecord {
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 8c8bead8c45..bd34fabf1b4 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -35,6 +35,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "ipc/ipc_message_macros.h"
+#include "net/http/http_util.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "url/gurl.h"
@@ -51,6 +52,12 @@ const char kShutdownErrorMessage[] =
const char kUserDeniedPermissionMessage[] =
"The user denied permission to use Service Worker.";
const char kInvalidStateErrorMessage[] = "The object is in an invalid state.";
+const char kEnableNavigationPreloadErrorPrefix[] =
+ "Failed to enable or disable navigation preload: ";
+const char kGetNavigationPreloadStateErrorPrefix[] =
+ "Failed to get navigation preload state: ";
+const char kSetNavigationPreloadHeaderErrorPrefix[] =
+ "Failed to set navigation preload header: ";
const uint32_t kFilteredMessageClasses[] = {
ServiceWorkerMsgStart, EmbeddedWorkerMsgStart,
@@ -61,35 +68,6 @@ void RunSoon(const base::Closure& callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
}
-bool CanUnregisterServiceWorker(const GURL& document_url,
- const GURL& pattern) {
- DCHECK(document_url.is_valid());
- DCHECK(pattern.is_valid());
- return ServiceWorkerUtils::PassOriginEqualitySecurityCheck<GURL>(document_url,
- pattern) &&
- OriginCanAccessServiceWorkers(document_url) &&
- OriginCanAccessServiceWorkers(pattern);
-}
-
-bool CanUpdateServiceWorker(const GURL& document_url, const GURL& pattern) {
- DCHECK(document_url.is_valid());
- DCHECK(pattern.is_valid());
- DCHECK(OriginCanAccessServiceWorkers(document_url));
- DCHECK(OriginCanAccessServiceWorkers(pattern));
- return ServiceWorkerUtils::PassOriginEqualitySecurityCheck<GURL>(document_url,
- pattern);
-}
-
-bool CanGetRegistration(const GURL& document_url,
- const GURL& given_document_url) {
- DCHECK(document_url.is_valid());
- DCHECK(given_document_url.is_valid());
- return ServiceWorkerUtils::PassOriginEqualitySecurityCheck<GURL>(
- document_url, given_document_url) &&
- OriginCanAccessServiceWorkers(document_url) &&
- OriginCanAccessServiceWorkers(given_document_url);
-}
-
} // namespace
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
@@ -101,7 +79,12 @@ ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
render_process_id_(render_process_id),
message_port_message_filter_(message_port_message_filter),
resource_context_(resource_context),
- channel_ready_(false) {
+ channel_ready_(false),
+ weak_factory_(this) {
+ AddAssociatedInterface(
+ mojom::ServiceWorkerDispatcherHost::Name_,
+ base::Bind(&ServiceWorkerDispatcherHost::AddMojoBinding,
+ base::Unretained(this)));
}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
@@ -206,6 +189,12 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
OnDecrementRegistrationRefCount)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_EnableNavigationPreload,
+ OnEnableNavigationPreload)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetNavigationPreloadState,
+ OnGetNavigationPreloadState)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetNavigationPreloadHeader,
+ OnSetNavigationPreloadHeader)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -219,6 +208,13 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
return handled;
}
+void ServiceWorkerDispatcherHost::AddMojoBinding(
+ mojo::ScopedInterfaceEndpointHandle handle) {
+ bindings_.AddBinding(
+ this, mojo::MakeAssociatedRequest<mojom::ServiceWorkerDispatcherHost>(
+ std::move(handle)));
+}
+
bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
if (channel_ready_) {
BrowserMessageFilter::Send(message);
@@ -286,45 +282,44 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
const GURL& script_url) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
- if (!GetContext()) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
+ base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
}
+
if (!pattern.is_valid() || !script_url.is_valid()) {
bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_BAD_URL);
return;
}
- ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
- render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_NO_HOST);
- return;
- }
- if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
- // TODO(ksakamoto): Currently, document_url is empty if the document is in an
- // IFRAME using frame.contentDocument.write(...). We can remove this check
- // once crbug.com/439697 is fixed.
- if (provider_host->document_url().is_empty()) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
- base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ std::string error_message;
+ if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
+ &error_message)) {
+ bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
return;
}
- if (!ServiceWorkerUtils::CanRegisterServiceWorker(
- provider_host->document_url(), pattern, script_url)) {
+ std::vector<GURL> urls = {provider_host->document_url(), pattern, script_url};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
// Temporary debugging for https://crbug.com/630495
base::debug::ScopedCrashKey host_url_key(
"swdh_register_cannot_host_url", provider_host->document_url().spec());
@@ -336,13 +331,6 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
return;
}
- std::string error_message;
- if (ServiceWorkerUtils::ContainsDisallowedCharacter(pattern, script_url,
- &error_message)) {
- bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
- return;
- }
-
if (!GetContentClient()->browser()->AllowServiceWorker(
pattern, provider_host->topmost_frame_url(), resource_context_,
render_process_id_, provider_host->frame_id())) {
@@ -374,35 +362,28 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
int64_t registration_id) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnUpdateServiceWorker");
- if (!GetContext()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
+ ProviderStatus provider_status;
ServiceWorkerProviderHost* provider_host =
- GetContext()->GetProviderHost(render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
- return;
- }
- if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
- // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
- if (provider_host->document_url().is_empty()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
- base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
- return;
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
+ base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
}
ServiceWorkerRegistration* registration =
@@ -415,8 +396,9 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
return;
}
- if (!CanUpdateServiceWorker(provider_host->document_url(),
- registration->pattern())) {
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
bad_message::ReceivedBadMessage(this, bad_message::SWDH_UPDATE_CANNOT);
return;
}
@@ -458,32 +440,29 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
int64_t registration_id) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
- if (!GetContext()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
+ ProviderStatus provider_status;
ServiceWorkerProviderHost* provider_host =
- GetContext()->GetProviderHost(render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(this, bad_message::SWDH_UNREGISTER_NO_HOST);
- return;
- }
- if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
- // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
- if (provider_host->document_url().is_empty()) {
- Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
- return;
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(this,
+ bad_message::SWDH_UNREGISTER_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) +
+ base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
}
ServiceWorkerRegistration* registration =
@@ -496,8 +475,9 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
return;
}
- if (!CanUnregisterServiceWorker(provider_host->document_url(),
- registration->pattern())) {
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
// Temporary debugging for https://crbug.com/619294
base::debug::ScopedCrashKey host_url_key(
"swdh_unregister_cannot_host_url",
@@ -535,44 +515,39 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnGetRegistration");
- if (!GetContext()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_REGISTRATION_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
+ base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
}
+
if (!document_url.is_valid()) {
bad_message::ReceivedBadMessage(this,
bad_message::SWDH_GET_REGISTRATION_BAD_URL);
return;
}
- ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
- render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(this,
- bad_message::SWDH_GET_REGISTRATION_NO_HOST);
- return;
- }
- if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
- // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed.
- if (provider_host->document_url().is_empty()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
- base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
- return;
- }
-
- if (!CanGetRegistration(provider_host->document_url(), document_url)) {
+ std::vector<GURL> urls = {provider_host->document_url(), document_url};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
// Temporary debugging for https://crbug.com/630496
base::debug::ScopedCrashKey host_url_key(
"swdh_get_registration_cannot_host_url",
@@ -613,36 +588,29 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnGetRegistrations");
- if (!GetContext()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
+ ProviderStatus provider_status;
ServiceWorkerProviderHost* provider_host =
- GetContext()->GetProviderHost(render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
- return;
- }
- if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
- base::ASCIIToUTF16(kShutdownErrorMessage)));
- return;
- }
-
- // TODO(jungkees): This check can be removed once crbug.com/439697 is fixed.
- if (provider_host->document_url().is_empty()) {
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
- base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
- return;
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
+ thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_REGISTRATIONS_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
+ base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
}
if (!OriginCanAccessServiceWorkers(provider_host->document_url())) {
@@ -699,6 +667,209 @@ void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
}
}
+void ServiceWorkerDispatcherHost::OnEnableNavigationPreload(
+ int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id,
+ bool enable) {
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ std::string(kEnableNavigationPreloadErrorPrefix) +
+ std::string(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_ENABLE_NAVIGATION_PRELOAD_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ std::string(kEnableNavigationPreloadErrorPrefix) +
+ std::string(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
+ }
+
+ ServiceWorkerRegistration* registration =
+ GetContext()->GetLiveRegistration(registration_id);
+ if (!registration) {
+ // |registration| must be alive because a renderer retains a registration
+ // reference at this point.
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID);
+ return;
+ }
+
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_ENABLE_NAVIGATION_PRELOAD_INVALID_ORIGIN);
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ registration->pattern(), provider_host->topmost_frame_url(),
+ resource_context_, render_process_id_, provider_host->frame_id())) {
+ Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeDisabled,
+ std::string(kEnableNavigationPreloadErrorPrefix) +
+ std::string(kUserDeniedPermissionMessage)));
+ return;
+ }
+
+ // TODO(falken): Write to disk before resolving the promise.
+ registration->EnableNavigationPreload(enable);
+ Send(new ServiceWorkerMsg_DidEnableNavigationPreload(thread_id, request_id));
+}
+
+void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState(
+ int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id) {
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
+ }
+
+ ServiceWorkerRegistration* registration =
+ GetContext()->GetLiveRegistration(registration_id);
+ if (!registration) {
+ // |registration| must be alive because a renderer retains a registration
+ // reference at this point.
+ bad_message::ReceivedBadMessage(
+ this,
+ bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID);
+ return;
+ }
+
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN);
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ registration->pattern(), provider_host->topmost_frame_url(),
+ resource_context_, render_process_id_, provider_host->frame_id())) {
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeDisabled,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kUserDeniedPermissionMessage)));
+ return;
+ }
+
+ Send(new ServiceWorkerMsg_DidGetNavigationPreloadState(
+ thread_id, request_id,
+ NavigationPreloadState(registration->is_navigation_preload_enabled(),
+ registration->navigation_preload_header())));
+}
+
+void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader(
+ int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id,
+ const std::string& value) {
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ std::string(kSetNavigationPreloadHeaderErrorPrefix) +
+ std::string(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ std::string(kSetNavigationPreloadHeaderErrorPrefix) +
+ std::string(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
+ }
+
+ ServiceWorkerRegistration* registration =
+ GetContext()->GetLiveRegistration(registration_id);
+ if (!registration) {
+ // |registration| must be alive because a renderer retains a registration
+ // reference at this point.
+ bad_message::ReceivedBadMessage(
+ this,
+ bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_REGISTRATION_ID);
+ return;
+ }
+
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_INVALID_ORIGIN);
+ return;
+ }
+
+ // TODO(falken): Ideally this would match Blink's isValidHTTPHeaderValue.
+ // Chrome's check is less restrictive: it allows non-latin1 characters.
+ if (!net::HttpUtil::IsValidHeaderValue(value)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_VALUE);
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ registration->pattern(), provider_host->topmost_frame_url(),
+ resource_context_, render_process_id_, provider_host->frame_id())) {
+ Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeDisabled,
+ std::string(kSetNavigationPreloadHeaderErrorPrefix) +
+ std::string(kUserDeniedPermissionMessage)));
+ return;
+ }
+
+ // TODO(falken): Write to disk before resolving the promise.
+ registration->SetNavigationPreloadHeader(value);
+ Send(new ServiceWorkerMsg_DidSetNavigationPreloadHeader(thread_id,
+ request_id));
+}
+
void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
int handle_id,
int provider_id,
@@ -1450,6 +1621,36 @@ ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
return context_wrapper_->context();
}
+ServiceWorkerProviderHost*
+ServiceWorkerDispatcherHost::GetProviderHostForRequest(ProviderStatus* status,
+ int provider_id) {
+ if (!GetContext()) {
+ *status = ProviderStatus::NO_CONTEXT;
+ return nullptr;
+ }
+
+ ServiceWorkerProviderHost* provider_host =
+ GetContext()->GetProviderHost(render_process_id_, provider_id);
+ if (!provider_host) {
+ *status = ProviderStatus::NO_HOST;
+ return nullptr;
+ }
+
+ if (!provider_host->IsContextAlive()) {
+ *status = ProviderStatus::DEAD_HOST;
+ return nullptr;
+ }
+
+ // TODO(falken): This check can be removed once crbug.com/439697 is fixed.
+ if (provider_host->document_url().is_empty()) {
+ *status = ProviderStatus::NO_URL;
+ return nullptr;
+ }
+
+ *status = ProviderStatus::OK;
+ return provider_host;
+}
+
void ServiceWorkerDispatcherHost::OnTerminateWorker(int handle_id) {
ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
if (!handle) {
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 bcd1dd8f721..5037c370c96 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -15,15 +15,17 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_message_filter.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
class GURL;
struct EmbeddedWorkerHostMsg_ReportConsoleMessage_Params;
namespace url {
class Origin;
-}
+} // namespace url
namespace content {
@@ -37,11 +39,12 @@ class ServiceWorkerRegistration;
class ServiceWorkerRegistrationHandle;
class ServiceWorkerVersion;
struct ServiceWorkerObjectInfo;
-struct ServiceWorkerRegistrationInfo;
struct ServiceWorkerRegistrationObjectInfo;
struct ServiceWorkerVersionAttributes;
-class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
+class CONTENT_EXPORT ServiceWorkerDispatcherHost
+ : public mojom::ServiceWorkerDispatcherHost,
+ public BrowserMessageFilter {
public:
ServiceWorkerDispatcherHost(
int render_process_id,
@@ -91,6 +94,17 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
friend class TestingServiceWorkerDispatcherHost;
using StatusCallback = base::Callback<void(ServiceWorkerStatusCode status)>;
+ enum class ProviderStatus { OK, NO_CONTEXT, DEAD_HOST, NO_HOST, NO_URL };
+
+ // Called when mojom::ServiceWorkerDispatcherHostPtr is created on the
+ // renderer-side.
+ void AddMojoBinding(mojo::ScopedInterfaceEndpointHandle handle);
+
+ // mojom::ServiceWorkerDispatcherHost implementation
+ void OnProviderCreated(int provider_id,
+ int route_id,
+ ServiceWorkerProviderType provider_type,
+ bool is_parent_frame_secure) override;
// IPC Message handlers
void OnRegisterServiceWorker(int thread_id,
@@ -114,10 +128,20 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
void OnGetRegistrationForReady(int thread_id,
int request_id,
int provider_id);
- void OnProviderCreated(int provider_id,
- int route_id,
- ServiceWorkerProviderType provider_type,
- bool is_parent_frame_secure);
+ void OnEnableNavigationPreload(int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id,
+ bool enable);
+ void OnGetNavigationPreloadState(int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id);
+ void OnSetNavigationPreloadHeader(int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id,
+ const std::string& value);
void OnProviderDestroyed(int provider_id);
void OnSetHostedVersionId(int provider_id,
int64_t version_id,
@@ -228,6 +252,12 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
ServiceWorkerRegistration* registration);
ServiceWorkerContextCore* GetContext();
+ // Returns the provider host with id equal to |provider_id|, or nullptr
+ // if the provider host could not be found or is not appropriate for
+ // initiating a request such as register/unregister/update.
+ ServiceWorkerProviderHost* GetProviderHostForRequest(
+ ProviderStatus* out_status,
+ int provider_id);
const int render_process_id_;
MessagePortMessageFilter* const message_port_message_filter_;
@@ -243,6 +273,10 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL.
std::vector<std::unique_ptr<IPC::Message>> pending_messages_;
+ mojo::AssociatedBindingSet<mojom::ServiceWorkerDispatcherHost> bindings_;
+
+ base::WeakPtrFactory<ServiceWorkerDispatcherHost> weak_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 14c618a69a2..74822260e9d 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
@@ -22,8 +22,10 @@
#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_handle.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_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
@@ -60,7 +62,7 @@ class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
ServiceWorkerContextWrapper* context_wrapper,
ResourceContext* resource_context,
EmbeddedWorkerTestHelper* helper)
- : ServiceWorkerDispatcherHost(process_id, NULL, resource_context),
+ : ServiceWorkerDispatcherHost(process_id, nullptr, resource_context),
bad_messages_received_count_(0),
helper_(helper) {
Init(context_wrapper);
@@ -256,6 +258,9 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
ServiceWorkerProviderHost* provider_host_;
};
+class ServiceWorkerDispatcherHostTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerDispatcherHostTest> {};
+
class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
public:
ServiceWorkerTestContentBrowserClient() {}
@@ -268,7 +273,7 @@ class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
}
};
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
Register_ContentSettingsDisallowsServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
@@ -302,7 +307,7 @@ TEST_F(ServiceWorkerDispatcherHostTest,
SetBrowserClientForTesting(old_browser_client);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_HTTPS) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_HTTPS) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -315,7 +320,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_HTTPS) {
ServiceWorkerMsg_ServiceWorkerRegistered::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureTransportLocalhost) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_NonSecureTransportLocalhost) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -328,7 +333,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureTransportLocalhost) {
ServiceWorkerMsg_ServiceWorkerRegistered::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScopeShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_InvalidScopeShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -340,7 +345,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScopeShouldFail) {
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScriptShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_InvalidScriptShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -351,7 +356,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScriptShouldFail) {
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureOriginShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_NonSecureOriginShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -364,7 +369,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureOriginShouldFail) {
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_CrossOriginShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -408,7 +413,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, Register_BadCharactersShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, Register_BadCharactersShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -440,7 +445,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_BadCharactersShouldFail) {
EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
Register_FileSystemDocumentShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -464,7 +469,7 @@ TEST_F(ServiceWorkerDispatcherHostTest,
EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
Register_FileSystemScriptOrScopeShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -488,7 +493,7 @@ TEST_F(ServiceWorkerDispatcherHostTest,
EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
+TEST_P(ServiceWorkerDispatcherHostTestP, EarlyContextDeletion) {
helper_->ShutdownContext();
// Let the shutdown reach the simulated IO thread.
@@ -500,7 +505,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
+TEST_P(ServiceWorkerDispatcherHostTestP, ProviderCreatedAndDestroyed) {
const int kProviderId = 1001;
int process_id = helper_->mock_render_process_id();
@@ -535,7 +540,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
}
-TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) {
+TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistration_SameOrigin) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -547,7 +552,8 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) {
ServiceWorkerMsg_DidGetRegistration::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_CrossOriginShouldFail) {
+TEST_P(ServiceWorkerDispatcherHostTestP,
+ GetRegistration_CrossOriginShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -558,7 +564,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_CrossOriginShouldFail) {
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
GetRegistration_InvalidScopeShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -570,7 +576,7 @@ TEST_F(ServiceWorkerDispatcherHostTest,
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
GetRegistration_NonSecureOriginShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -582,7 +588,7 @@ TEST_F(ServiceWorkerDispatcherHostTest,
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_EarlyContextDeletion) {
+TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistration_EarlyContextDeletion) {
helper_->ShutdownContext();
// Let the shutdown reach the simulated IO thread.
@@ -593,7 +599,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_EarlyContextDeletion) {
ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_SecureOrigin) {
+TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistrations_SecureOrigin) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
@@ -603,7 +609,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_SecureOrigin) {
GetRegistrations(kProviderId, ServiceWorkerMsg_DidGetRegistrations::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest,
+TEST_P(ServiceWorkerDispatcherHostTestP,
GetRegistrations_NonSecureOriginShouldFail) {
const int64_t kProviderId = 99; // Dummy value
std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -615,7 +621,8 @@ TEST_F(ServiceWorkerDispatcherHostTest,
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_EarlyContextDeletion) {
+TEST_P(ServiceWorkerDispatcherHostTestP,
+ GetRegistrations_EarlyContextDeletion) {
helper_->ShutdownContext();
// Let the shutdown reach the simulated IO thread.
@@ -624,7 +631,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_EarlyContextDeletion) {
GetRegistrations(-1, ServiceWorkerMsg_ServiceWorkerGetRegistrationsError::ID);
}
-TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
+TEST_P(ServiceWorkerDispatcherHostTestP, CleanupOnRendererCrash) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
int process_id = helper_->mock_render_process_id();
@@ -669,7 +676,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
+TEST_P(ServiceWorkerDispatcherHostTestP, DispatchExtendableMessageEvent) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
@@ -709,7 +716,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
}
-TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
+TEST_P(ServiceWorkerDispatcherHostTestP, DispatchExtendableMessageEvent_Fail) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
@@ -750,7 +757,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
EXPECT_EQ(ref_count, sender_worker_handle->ref_count());
}
-TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
+TEST_P(ServiceWorkerDispatcherHostTestP, OnSetHostedVersionId) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
@@ -778,7 +785,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId_DetachedWorker) {
+TEST_P(ServiceWorkerDispatcherHostTestP, OnSetHostedVersionId_DetachedWorker) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
@@ -806,7 +813,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId_DetachedWorker) {
EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
+TEST_P(ServiceWorkerDispatcherHostTestP, ReceivedTimedOutRequestResponse) {
GURL pattern = GURL("https://www.example.com/");
GURL script_url = GURL("https://www.example.com/service_worker.js");
@@ -823,9 +830,9 @@ TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
// Receive a response for a timed out request. The bad message count should
// not increase.
- const int kRequestId = 91; // Dummy value
+ const int kFetchEventId = 91; // Dummy value
dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_FetchEventResponse(
- version_->embedded_worker()->embedded_worker_id(), kRequestId,
+ version_->embedded_worker()->embedded_worker_id(), kFetchEventId,
SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, ServiceWorkerResponse(),
base::Time::Now()));
@@ -833,4 +840,8 @@ TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerDispatcherHostTest,
+ ServiceWorkerDispatcherHostTestP,
+ testing::Bool());
+
} // 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 7d71218ea20..a105a486318 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -8,21 +8,107 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/fetch_event_dispatcher.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/http/http_util.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/url_request/url_request.h"
namespace content {
namespace {
+// This class wraps a mojo::AssociatedInterfacePtr<URLLoader>. It also is a
+// URLLoader implementation and delegates URLLoader calls to the wrapped loader.
+class DelegatingURLLoader final : public mojom::URLLoader {
+ public:
+ explicit DelegatingURLLoader(mojom::URLLoaderAssociatedPtr loader)
+ : binding_(this), loader_(std::move(loader)) {}
+ ~DelegatingURLLoader() override {}
+
+ void FollowRedirect() override { loader_->FollowRedirect(); }
+
+ mojom::URLLoaderPtr CreateInterfacePtrAndBind() {
+ auto p = binding_.CreateInterfacePtrAndBind();
+ // 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)));
+ return p;
+ }
+
+ private:
+ // Called when the mojom::URLLoaderPtr in the service worker is deleted.
+ void Cancel() {
+ // Cancel loading as stated in url_loader.mojom.
+ loader_ = nullptr;
+ }
+
+ mojo::Binding<mojom::URLLoader> binding_;
+ mojom::URLLoaderAssociatedPtr loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader);
+};
+
+// This class wraps a mojo::InterfacePtr<URLLoaderClient>. It also is a
+// URLLoaderClient implementation and delegates URLLoaderClient calls to the
+// wrapped client.
+class DelegatingURLLoaderClient final : public mojom::URLLoaderClient {
+ public:
+ explicit DelegatingURLLoaderClient(mojom::URLLoaderClientPtr client)
+ : binding_(this), client_(std::move(client)) {}
+ ~DelegatingURLLoaderClient() override {}
+
+ void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {
+ client_->OnDataDownloaded(data_length, encoded_length);
+ }
+ void OnReceiveResponse(const ResourceResponseHead& head) override {
+ client_->OnReceiveResponse(head);
+ }
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& head) override {
+ client_->OnReceiveRedirect(redirect_info, head);
+ }
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override {
+ client_->OnStartLoadingResponseBody(std::move(body));
+ }
+ void OnComplete(
+ const ResourceRequestCompletionStatus& completion_status) override {
+ client_->OnComplete(completion_status);
+ }
+
+ void Bind(mojom::URLLoaderClientAssociatedPtrInfo* ptr_info,
+ mojo::AssociatedGroup* associated_group) {
+ binding_.Bind(ptr_info, associated_group);
+ }
+
+ private:
+ mojo::AssociatedBinding<mojom::URLLoaderClient> binding_;
+ mojom::URLLoaderClientPtr client_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoaderClient);
+};
+
using EventType = ServiceWorkerMetrics::EventType;
EventType ResourceTypeToEventType(ResourceType resource_type) {
switch (resource_type) {
@@ -74,6 +160,18 @@ ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType(
return ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL;
}
+void OnFetchEventFinished(
+ ServiceWorkerVersion* version,
+ int event_finish_id,
+ mojom::URLLoaderFactoryPtr url_loader_factory,
+ std::unique_ptr<mojom::URLLoader> url_loader,
+ std::unique_ptr<mojom::URLLoaderClient> url_loader_client,
+ ServiceWorkerStatusCode status,
+ base::Time dispatch_event_time) {
+ version->FinishRequest(event_finish_id, status != SERVICE_WORKER_ERROR_ABORT,
+ dispatch_event_time);
+}
+
} // namespace
// Helper to receive the fetch event response even if
@@ -197,7 +295,7 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
prepare_callback.Run();
net_log_.BeginEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
- int response_id = version_->StartRequest(
+ int fetch_event_id = version_->StartRequest(
GetEventType(),
base::Bind(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
weak_factory_.GetWeakPtr()));
@@ -208,14 +306,24 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
ResponseCallback* response_callback =
new ResponseCallback(weak_factory_.GetWeakPtr(), version_.get());
version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>(
- response_id,
+ fetch_event_id,
base::Bind(&ServiceWorkerFetchDispatcher::ResponseCallback::Run,
base::Owned(response_callback)));
- version_->RegisterSimpleRequest<ServiceWorkerHostMsg_FetchEventFinished>(
- event_finish_id);
- version_->DispatchEvent({response_id, event_finish_id},
- ServiceWorkerMsg_FetchEvent(
- response_id, event_finish_id, *request_.get()));
+
+ base::WeakPtr<mojom::FetchEventDispatcher> dispatcher =
+ version_->GetMojoServiceForRequest<mojom::FetchEventDispatcher>(
+ event_finish_id);
+ // |dispatcher| is owned by |version_|. So it is safe to pass the unretained
+ // raw pointer of |version_| to OnFetchEventFinished callback.
+ // Pass |url_loader_factory_|, |url_Loader_| and |url_loader_client_| to the
+ // callback to keep them alive while the FetchEvent is onging in the service
+ // worker.
+ dispatcher->DispatchFetchEvent(
+ fetch_event_id, *request_, std::move(preload_handle_),
+ base::Bind(&OnFetchEventFinished, base::Unretained(version_.get()),
+ event_finish_id, base::Passed(std::move(url_loader_factory_)),
+ base::Passed(std::move(url_loader_)),
+ base::Passed(std::move(url_loader_client_))));
}
void ServiceWorkerFetchDispatcher::DidFailToDispatch(
@@ -255,6 +363,90 @@ void ServiceWorkerFetchDispatcher::Complete(
fetch_callback.Run(status, fetch_result, response, version);
}
+void ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
+ net::URLRequest* original_request) {
+ if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME &&
+ resource_type_ != RESOURCE_TYPE_SUB_FRAME) {
+ return;
+ }
+ if (!version_->navigation_preload_state().enabled)
+ return;
+ // TODO(horo): Currently NavigationPreload doesn't support request body.
+ if (!request_->blob_uuid.empty())
+ return;
+ if (!base::FeatureList::IsEnabled(
+ features::kServiceWorkerNavigationPreload)) {
+ // TODO(horo): Check |version_|'s origin_trial_tokens() here if we use
+ // Origin-Trial for NavigationPreload.
+ return;
+ }
+ if (IsBrowserSideNavigationEnabled()) {
+ // TODO(horo): Support NavigationPreload with PlzNavigate.
+ NOTIMPLEMENTED();
+ return;
+ }
+
+ DCHECK(!url_loader_factory_);
+ const ResourceRequestInfoImpl* original_info =
+ ResourceRequestInfoImpl::ForRequest(original_request);
+ if (!original_info->filter())
+ return;
+ mojom::URLLoaderFactoryPtr factory;
+ URLLoaderFactoryImpl::Create(original_info->filter(),
+ mojo::GetProxy(&url_loader_factory_));
+
+ preload_handle_ = mojom::FetchEventPreloadHandle::New();
+
+ ResourceRequest request;
+ request.method = original_request->method();
+ request.url = original_request->url();
+ request.request_initiator = original_request->initiator();
+ request.referrer = GURL(original_request->referrer());
+ request.referrer_policy = original_info->GetReferrerPolicy();
+ request.visibility_state = original_info->GetVisibilityState();
+ request.load_flags = original_request->load_flags();
+ // Set to SUB_RESOURCE because we shouldn't trigger NavigationResourceThrottle
+ // for the service worker navigation preload request.
+ request.resource_type = RESOURCE_TYPE_SUB_RESOURCE;
+ request.priority = original_request->priority();
+ request.skip_service_worker = SkipServiceWorker::ALL;
+ request.do_not_prompt_for_login = true;
+ request.render_frame_id = original_info->GetRenderFrameID();
+ request.is_main_frame = original_info->IsMainFrame();
+ request.parent_is_main_frame = original_info->ParentIsMainFrame();
+
+ DCHECK(net::HttpUtil::IsValidHeaderValue(
+ version_->navigation_preload_state().header));
+ request.headers = "Service-Worker-Navigation-Preload: " +
+ version_->navigation_preload_state().header;
+
+ const int request_id = ResourceDispatcherHostImpl::Get()->MakeRequestID();
+ DCHECK_LT(request_id, -1);
+
+ preload_handle_ = mojom::FetchEventPreloadHandle::New();
+ mojom::URLLoaderClientPtr url_loader_client_ptr;
+ preload_handle_->url_loader_client_request =
+ mojo::GetProxy(&url_loader_client_ptr);
+ auto url_loader_client = base::MakeUnique<DelegatingURLLoaderClient>(
+ std::move(url_loader_client_ptr));
+ mojom::URLLoaderClientAssociatedPtrInfo url_loader_client_associated_ptr_info;
+ url_loader_client->Bind(&url_loader_client_associated_ptr_info,
+ url_loader_factory_.associated_group());
+ mojom::URLLoaderAssociatedPtr url_loader_associated_ptr;
+
+ url_loader_factory_->CreateLoaderAndStart(
+ mojo::GetProxy(&url_loader_associated_ptr,
+ url_loader_factory_.associated_group()),
+ original_info->GetRouteID(), request_id, request,
+ std::move(url_loader_client_associated_ptr_info));
+
+ std::unique_ptr<DelegatingURLLoader> url_loader(
+ new DelegatingURLLoader(std::move(url_loader_associated_ptr)));
+ preload_handle_->url_loader = url_loader->CreateInterfacePtrAndBind();
+ url_loader_ = std::move(url_loader);
+ url_loader_client_ = std::move(url_loader_client);
+}
+
ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()
const {
if (request_->fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH)
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 0011f475ca6..5e05291e231 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -5,16 +5,25 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
+#include "content/common/service_worker/fetch_event_dispatcher.mojom.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/common/url_loader.mojom.h"
+#include "content/common/url_loader_factory.mojom.h"
#include "content/public/common/resource_type.h"
#include "net/log/net_log_with_source.h"
+namespace net {
+class URLRequest;
+} // namespace net
+
namespace content {
class ServiceWorkerVersion;
@@ -22,11 +31,11 @@ class ServiceWorkerVersion;
// A helper class to dispatch fetch event to a service worker.
class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
public:
- typedef base::Callback<void(ServiceWorkerStatusCode,
- ServiceWorkerFetchEventResult,
- const ServiceWorkerResponse&,
- const scoped_refptr<ServiceWorkerVersion>&)>
- FetchCallback;
+ using FetchCallback =
+ base::Callback<void(ServiceWorkerStatusCode,
+ ServiceWorkerFetchEventResult,
+ const ServiceWorkerResponse&,
+ const scoped_refptr<ServiceWorkerVersion>&)>;
ServiceWorkerFetchDispatcher(
std::unique_ptr<ServiceWorkerFetchRequest> request,
@@ -37,6 +46,10 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
const FetchCallback& fetch_callback);
~ServiceWorkerFetchDispatcher();
+ // If appropriate, starts the navigation preload request and creates
+ // |preload_handle_|.
+ void MaybeStartNavigationPreload(net::URLRequest* original_request);
+
// Dispatches a fetch event to the |version| given in ctor, and fires
// |fetch_callback| (also given in ctor) when finishes. It runs
// |prepare_callback| as an intermediate step once the version is activated
@@ -69,6 +82,11 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
std::unique_ptr<ServiceWorkerFetchRequest> request_;
ResourceType resource_type_;
bool did_complete_;
+ mojom::URLLoaderFactoryPtr url_loader_factory_;
+ std::unique_ptr<mojom::URLLoader> url_loader_;
+ std::unique_ptr<mojom::URLLoaderClient> url_loader_client_;
+ mojom::FetchEventPreloadHandlePtr preload_handle_;
+
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_handle.h
index 6a519ea56c3..9cc393ded29 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_handle.h
@@ -14,10 +14,6 @@
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
-namespace IPC {
-class Sender;
-}
-
namespace content {
class ServiceWorkerContextCore;
diff --git a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
index 4767ecb01b1..e97a64c5e3d 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -17,6 +17,7 @@
#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/common/service_worker/service_worker_types.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_message.h"
@@ -141,7 +142,10 @@ class ServiceWorkerHandleTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandleTest);
};
-TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
+class ServiceWorkerHandleTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerHandleTest> {};
+
+TEST_P(ServiceWorkerHandleTestP, OnVersionStateChanged) {
std::unique_ptr<ServiceWorkerHandle> handle =
ServiceWorkerHandle::Create(helper_->context()->AsWeakPtr(),
provider_host_->AsWeakPtr(), version_.get());
@@ -156,16 +160,27 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
// ...update state to installed.
version_->SetStatus(ServiceWorkerVersion::INSTALLED);
- ASSERT_EQ(2UL, ipc_sink()->message_count());
ASSERT_EQ(0L, dispatcher_host_->bad_message_received_count_);
- // We should be sending 1. StartWorker,
- EXPECT_EQ(EmbeddedWorkerMsg_StartWorker::ID,
- ipc_sink()->GetMessageAt(0)->type());
- // 2. StateChanged (state == Installed).
+ const IPC::Message* message = nullptr;
+ if (is_mojo_enabled()) {
+ // StartWorker shouldn't be recorded here.
+ ASSERT_EQ(1UL, ipc_sink()->message_count());
+ message = ipc_sink()->GetMessageAt(0);
+ } else {
+ ASSERT_EQ(2UL, ipc_sink()->message_count());
+ // We should be sending 1. StartWorker,
+ EXPECT_EQ(EmbeddedWorkerMsg_StartWorker::ID,
+ ipc_sink()->GetMessageAt(0)->type());
+ message = ipc_sink()->GetMessageAt(1);
+ }
+ // StateChanged (state == Installed).
VerifyStateChangedMessage(handle->handle_id(),
- blink::WebServiceWorkerStateInstalled,
- ipc_sink()->GetMessageAt(1));
+ blink::WebServiceWorkerStateInstalled, message);
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerHandleTest,
+ ServiceWorkerHandleTestP,
+ ::testing::Values(false, true));
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.h b/chromium/content/browser/service_worker/service_worker_internals_ui.h
index 21fdc6f9106..f1bed17e6b6 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.h
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.h
@@ -18,7 +18,6 @@
namespace base {
class ListValue;
-class DictionaryValue;
}
namespace content {
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 28d537dbca0..27957f17eb0 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
@@ -10,7 +10,6 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
namespace content {
@@ -23,48 +22,46 @@ bool IsRegisterJob(const ServiceWorkerRegisterJobBase& job) {
}
-ServiceWorkerJobCoordinator::JobQueue::JobQueue() {}
+ServiceWorkerJobCoordinator::JobQueue::JobQueue() = default;
-ServiceWorkerJobCoordinator::JobQueue::JobQueue(const JobQueue& other) =
- default;
+ServiceWorkerJobCoordinator::JobQueue::JobQueue(JobQueue&&) = default;
ServiceWorkerJobCoordinator::JobQueue::~JobQueue() {
DCHECK(jobs_.empty()) << "Destroying JobQueue with " << jobs_.size()
<< " unfinished jobs";
- base::STLDeleteElements(&jobs_);
}
ServiceWorkerRegisterJobBase* ServiceWorkerJobCoordinator::JobQueue::Push(
std::unique_ptr<ServiceWorkerRegisterJobBase> job) {
if (jobs_.empty()) {
- jobs_.push_back(job.release());
+ jobs_.push_back(std::move(job));
StartOneJob();
- } else if (!job->Equals(jobs_.back())) {
- jobs_.push_back(job.release());
+ } else if (!job->Equals(jobs_.back().get())) {
+ jobs_.push_back(std::move(job));
DoomInstallingWorkerIfNeeded();
}
- // Note we are releasing 'job' here.
+ // Note we are releasing 'job' here in case neither of the two if() statements
+ // above were true.
DCHECK(!jobs_.empty());
- return jobs_.back();
+ return jobs_.back().get();
}
void ServiceWorkerJobCoordinator::JobQueue::Pop(
ServiceWorkerRegisterJobBase* job) {
- DCHECK(job == jobs_.front());
+ DCHECK(job == jobs_.front().get());
jobs_.pop_front();
- delete job;
if (!jobs_.empty())
StartOneJob();
}
void ServiceWorkerJobCoordinator::JobQueue::DoomInstallingWorkerIfNeeded() {
DCHECK(!jobs_.empty());
- if (!IsRegisterJob(*jobs_.front()))
+ if (!IsRegisterJob(*jobs_.front().get()))
return;
ServiceWorkerRegisterJob* job =
- static_cast<ServiceWorkerRegisterJob*>(jobs_.front());
- std::deque<ServiceWorkerRegisterJobBase*>::iterator it = jobs_.begin();
+ static_cast<ServiceWorkerRegisterJob*>(jobs_.front().get());
+ auto it = jobs_.begin();
for (++it; it != jobs_.end(); ++it) {
if (IsRegisterJob(**it)) {
job->DoomInstallingWorker();
@@ -80,13 +77,13 @@ void ServiceWorkerJobCoordinator::JobQueue::StartOneJob() {
}
void ServiceWorkerJobCoordinator::JobQueue::AbortAll() {
- for (size_t i = 0; i < jobs_.size(); ++i)
- jobs_[i]->Abort();
- base::STLDeleteElements(&jobs_);
+ for (const auto& job : jobs_)
+ job->Abort();
+ jobs_.clear();
}
void ServiceWorkerJobCoordinator::JobQueue::ClearForShutdown() {
- base::STLDeleteElements(&jobs_);
+ jobs_.clear();
}
ServiceWorkerJobCoordinator::ServiceWorkerJobCoordinator(
@@ -96,10 +93,8 @@ ServiceWorkerJobCoordinator::ServiceWorkerJobCoordinator(
ServiceWorkerJobCoordinator::~ServiceWorkerJobCoordinator() {
if (!context_) {
- for (RegistrationJobMap::iterator it = job_queues_.begin();
- it != job_queues_.end(); ++it) {
- it->second.ClearForShutdown();
- }
+ for (auto& job_pair : job_queues_)
+ job_pair.second.ClearForShutdown();
job_queues_.clear();
}
DCHECK(job_queues_.empty()) << "Destroying ServiceWorkerJobCoordinator with "
@@ -157,16 +152,14 @@ void ServiceWorkerJobCoordinator::Update(
}
void ServiceWorkerJobCoordinator::AbortAll() {
- for (RegistrationJobMap::iterator it = job_queues_.begin();
- it != job_queues_.end(); ++it) {
- it->second.AbortAll();
- }
+ for (auto& job_pair : job_queues_)
+ job_pair.second.AbortAll();
job_queues_.clear();
}
void ServiceWorkerJobCoordinator::FinishJob(const GURL& pattern,
ServiceWorkerRegisterJobBase* job) {
- RegistrationJobMap::iterator pending_jobs = job_queues_.find(pattern);
+ auto pending_jobs = job_queues_.find(pattern);
DCHECK(pending_jobs != job_queues_.end()) << "Deleting non-existent job.";
pending_jobs->second.Pop(job);
if (pending_jobs->second.empty())
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.h b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
index 23e48abf0d6..c309e0586a1 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.h
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
@@ -7,6 +7,7 @@
#include <deque>
#include <map>
+#include <memory>
#include "base/macros.h"
#include "content/browser/service_worker/service_worker_register_job.h"
@@ -16,10 +17,8 @@
namespace content {
-class EmbeddedWorkerRegistry;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
-class ServiceWorkerStorage;
// This class manages all in-flight registration or unregistration jobs.
class CONTENT_EXPORT ServiceWorkerJobCoordinator {
@@ -56,7 +55,7 @@ class CONTENT_EXPORT ServiceWorkerJobCoordinator {
class JobQueue {
public:
JobQueue();
- JobQueue(const JobQueue& other);
+ JobQueue(JobQueue&&);
~JobQueue();
// Adds a job to the queue. If an identical job is already at the end of the
@@ -87,15 +86,15 @@ class CONTENT_EXPORT ServiceWorkerJobCoordinator {
void ClearForShutdown();
private:
- std::deque<ServiceWorkerRegisterJobBase*> jobs_;
- };
+ std::deque<std::unique_ptr<ServiceWorkerRegisterJobBase>> jobs_;
- typedef std::map<GURL, JobQueue> RegistrationJobMap;
+ DISALLOW_COPY_AND_ASSIGN(JobQueue);
+ };
// The ServiceWorkerContextCore object should always outlive the
// job coordinator, the core owns the coordinator.
base::WeakPtr<ServiceWorkerContextCore> context_;
- RegistrationJobMap job_queues_;
+ std::map<GURL, JobQueue> job_queues_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerJobCoordinator);
};
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 50ed74f0556..5ea9d11a072 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -8,6 +8,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
@@ -142,6 +143,9 @@ class ServiceWorkerJobTest : public testing::Test {
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
};
+class ServiceWorkerJobTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerJobTest> {};
+
scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
const GURL& pattern,
const GURL& script_url,
@@ -195,7 +199,7 @@ ServiceWorkerJobTest::CreateControllee() {
helper_->context()->AsWeakPtr(), NULL));
}
-TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
+TEST_P(ServiceWorkerJobTestP, SameDocumentSameRegistration) {
scoped_refptr<ServiceWorkerRegistration> original_registration =
RunRegisterJob(GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"));
@@ -215,7 +219,7 @@ TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
ASSERT_EQ(registration1, registration2);
}
-TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
+TEST_P(ServiceWorkerJobTestP, SameMatchSameRegistration) {
bool called;
scoped_refptr<ServiceWorkerRegistration> original_registration =
RunRegisterJob(GURL("http://www.example.com/"),
@@ -240,7 +244,7 @@ TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
ASSERT_EQ(registration1, registration2);
}
-TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
+TEST_P(ServiceWorkerJobTestP, DifferentMatchDifferentRegistration) {
bool called1;
scoped_refptr<ServiceWorkerRegistration> original_registration1;
job_coordinator()->Register(
@@ -279,7 +283,7 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
}
// Make sure basic registration is working.
-TEST_F(ServiceWorkerJobTest, Register) {
+TEST_P(ServiceWorkerJobTestP, Register) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"));
@@ -290,7 +294,7 @@ TEST_F(ServiceWorkerJobTest, Register) {
}
// Make sure registrations are cleaned up when they are unregistered.
-TEST_F(ServiceWorkerJobTest, Unregister) {
+TEST_P(ServiceWorkerJobTestP, Unregister) {
GURL pattern("http://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -306,7 +310,7 @@ TEST_F(ServiceWorkerJobTest, Unregister) {
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
}
-TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
+TEST_P(ServiceWorkerJobTestP, Unregister_NothingRegistered) {
GURL pattern("http://www.example.com/");
RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
@@ -314,7 +318,7 @@ TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
// Make sure registering a new script creates a new version and shares an
// existing registration.
-TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
+TEST_P(ServiceWorkerJobTestP, RegisterNewScript) {
GURL pattern("http://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> old_registration =
@@ -340,7 +344,7 @@ 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) {
+TEST_P(ServiceWorkerJobTestP, RegisterDuplicateScript) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
@@ -379,7 +383,7 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
}
};
-TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
+TEST_P(ServiceWorkerJobTestP, Register_FailToStartWorker) {
helper_.reset(new FailToStartWorkerTestHelper);
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -392,7 +396,7 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
// Register and then unregister the pattern, in parallel. Job coordinator should
// process jobs until the last job.
-TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
+TEST_P(ServiceWorkerJobTestP, ParallelRegUnreg) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
@@ -424,7 +428,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
// Register conflicting scripts for the same pattern. The most recent
// registration should win, and the old registration should have been
// shutdown.
-TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
+TEST_P(ServiceWorkerJobTestP, ParallelRegNewScript) {
GURL pattern("http://www.example.com/");
GURL script_url1("http://www.example.com/service_worker1.js");
@@ -462,7 +466,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
// Register the exact same pattern + script. Requests should be
// coalesced such that both callers get the exact same registration
// object.
-TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
+TEST_P(ServiceWorkerJobTestP, ParallelRegSameScript) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker1.js");
@@ -499,7 +503,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
}
// Call simulataneous unregister calls.
-TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
+TEST_P(ServiceWorkerJobTestP, ParallelUnreg) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
@@ -530,7 +534,7 @@ TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
}
-TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
+TEST_P(ServiceWorkerJobTestP, AbortAll_Register) {
GURL pattern1("http://www1.example.com/");
GURL pattern2("http://www2.example.com/");
GURL script_url1("http://www1.example.com/service_worker.js");
@@ -581,7 +585,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
}
-TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
+TEST_P(ServiceWorkerJobTestP, AbortAll_Unregister) {
GURL pattern1("http://www1.example.com/");
GURL pattern2("http://www2.example.com/");
@@ -607,7 +611,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
ASSERT_TRUE(unregistration_called2);
}
-TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
+TEST_P(ServiceWorkerJobTestP, AbortAll_RegUnreg) {
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
@@ -642,7 +646,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
// Tests that the waiting worker enters the 'redundant' state upon
// unregistration.
-TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
+TEST_P(ServiceWorkerJobTestP, UnregisterWaitingSetsRedundant) {
GURL script_url("http://www.example.com/service_worker.js");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/"), script_url);
@@ -675,7 +679,7 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
// Tests that the active worker enters the 'redundant' state upon
// unregistration.
-TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
+TEST_P(ServiceWorkerJobTestP, UnregisterActiveSetsRedundant) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"));
@@ -695,7 +699,7 @@ TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
// Tests that the active worker enters the 'redundant' state upon
// unregistration.
-TEST_F(ServiceWorkerJobTest,
+TEST_P(ServiceWorkerJobTestP,
UnregisterActiveSetsRedundant_WaitForNoControllee) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/"),
@@ -961,7 +965,7 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
} // namespace
-TEST_F(ServiceWorkerJobTest, Update_NoChange) {
+TEST_P(ServiceWorkerJobTestP, Update_NoChange) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -999,7 +1003,7 @@ TEST_F(ServiceWorkerJobTest, Update_NoChange) {
EXPECT_FALSE(update_helper->update_found_);
}
-TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) {
+TEST_P(ServiceWorkerJobTestP, Update_BumpLastUpdateCheckTime) {
const base::Time kToday = base::Time::Now();
const base::Time kYesterday =
kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1);
@@ -1048,7 +1052,7 @@ TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) {
EXPECT_LT(kYesterday, registration->last_update_check());
}
-TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
+TEST_P(ServiceWorkerJobTestP, Update_NewVersion) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -1140,7 +1144,7 @@ TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
// Test that the update job uses the script URL of the newest worker when the
// job starts, rather than when it is scheduled.
-TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
+TEST_P(ServiceWorkerJobTestP, Update_ScriptUrlChanged) {
// Create a registration with an active version.
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/one/"),
@@ -1168,7 +1172,7 @@ TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
// Test that update succeeds if the incumbent worker was evicted
// during the update job (this can happen on disk cache failure).
-TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
+TEST_P(ServiceWorkerJobTestP, Update_EvictedIncumbent) {
EvictIncumbentVersionHelper* update_helper = new EvictIncumbentVersionHelper;
helper_.reset(update_helper);
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -1197,7 +1201,7 @@ TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
EXPECT_FALSE(registration->is_uninstalled());
}
-TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
+TEST_P(ServiceWorkerJobTestP, Update_UninstallingRegistration) {
bool called;
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("http://www.example.com/one/"),
@@ -1224,7 +1228,7 @@ TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
EXPECT_EQ(NULL, registration->installing_version());
}
-TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
+TEST_P(ServiceWorkerJobTestP, RegisterWhileUninstalling) {
GURL pattern("http://www.example.com/one/");
GURL script1("http://www.example.com/service_worker.js");
GURL script2("http://www.example.com/service_worker.js?new");
@@ -1275,7 +1279,7 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
}
-TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
+TEST_P(ServiceWorkerJobTestP, RegisterAndUnregisterWhileUninstalling) {
GURL pattern("http://www.example.com/one/");
GURL script1("http://www.example.com/service_worker.js");
GURL script2("http://www.example.com/service_worker.js?new");
@@ -1323,7 +1327,8 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
}
-TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
+TEST_P(ServiceWorkerJobTestP,
+ RegisterSameScriptMultipleTimesWhileUninstalling) {
GURL pattern("http://www.example.com/one/");
GURL script1("http://www.example.com/service_worker.js");
GURL script2("http://www.example.com/service_worker.js?new");
@@ -1374,7 +1379,7 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
}
-TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
+TEST_P(ServiceWorkerJobTestP, RegisterMultipleTimesWhileUninstalling) {
GURL pattern("http://www.example.com/one/");
GURL script1("http://www.example.com/service_worker.js?first");
GURL script2("http://www.example.com/service_worker.js?second");
@@ -1471,7 +1476,7 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
bool has_fetch_handler_ = true;
};
-TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
+TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringInstall) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
@@ -1511,7 +1516,7 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
}
-TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
+TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringRejectedInstall) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
@@ -1547,7 +1552,7 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
}
-TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
+TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringInstall_RejectActivate) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
@@ -1583,7 +1588,7 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
FindRegistrationForPattern(pattern, SERVICE_WORKER_OK);
}
-TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
+TEST_P(ServiceWorkerJobTestP, HasFetchHandler) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
@@ -1606,15 +1611,59 @@ TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
RunUnregisterJob(pattern);
}
-TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
+class CheckPauseAfterDownloadEmbeddedWorkerInstanceClient
+ : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient {
+ public:
+ explicit CheckPauseAfterDownloadEmbeddedWorkerInstanceClient(
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+ : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
+ int num_of_startworker() const { return num_of_startworker_; }
+ void set_next_pause_after_download(bool expectation) {
+ next_pause_after_download_ = expectation;
+ }
+
+ protected:
+ void StartWorker(
+ const EmbeddedWorkerStartParams& params,
+ service_manager::mojom::InterfaceProviderPtr browser_interfaces,
+ service_manager::mojom::InterfaceProviderRequest renderer_request)
+ 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(browser_interfaces), std::move(renderer_request));
+ }
+
+ private:
+ base::Optional<bool> next_pause_after_download_;
+ int num_of_startworker_ = 0;
+ DISALLOW_COPY_AND_ASSIGN(CheckPauseAfterDownloadEmbeddedWorkerInstanceClient);
+};
+
+TEST_P(ServiceWorkerJobTestP, Update_PauseAfterDownload) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
IPC::TestSink* sink = update_helper->ipc_sink();
+ std::vector<CheckPauseAfterDownloadEmbeddedWorkerInstanceClient*> clients;
+ if (is_mojo_enabled()) {
+ clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
+ CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
+ helper_->AsWeakPtr()));
+ clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
+ CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
+ helper_->AsWeakPtr()));
+ }
+
// The initial version should not pause after download.
+ if (is_mojo_enabled())
+ clients[0]->set_next_pause_after_download(false);
scoped_refptr<ServiceWorkerRegistration> registration =
update_helper->SetupInitialRegistration(kNewVersionOrigin);
- {
+ if (is_mojo_enabled()) {
+ ASSERT_EQ(1, clients[0]->num_of_startworker());
+ } else {
const IPC::Message* start_msg =
sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
ASSERT_TRUE(start_msg);
@@ -1626,10 +1675,14 @@ TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
}
// The updated version should pause after download.
+ if (is_mojo_enabled())
+ clients[1]->set_next_pause_after_download(true);
registration->AddListener(update_helper);
registration->active_version()->StartUpdate();
base::RunLoop().RunUntilIdle();
- {
+ if (is_mojo_enabled()) {
+ ASSERT_EQ(1, clients[1]->num_of_startworker());
+ } else {
const IPC::Message* start_msg =
sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
ASSERT_TRUE(start_msg);
@@ -1643,7 +1696,7 @@ TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
// Test that activation doesn't complete if it's triggered by removing a
// controllee and starting the worker failed due to shutdown.
-TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
+TEST_P(ServiceWorkerJobTestP, ActivateCancelsOnShutdown) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
GURL pattern("http://www.example.com/");
@@ -1698,4 +1751,8 @@ TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
registration->RemoveListener(update_helper);
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerJobTest,
+ ServiceWorkerJobTestP,
+ ::testing::Values(false, true));
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index e2459fd76c0..310e76e3d8a 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -78,6 +78,8 @@ std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_NAVIGATION_HINT_LINK_TAP_UNCONFIRMED";
case ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_TAP_DOWN:
return "_NAVIGATION_HINT_LINK_TAP_DOWN";
+ case ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST:
+ return "_EXTERNAL_REQUEST";
case ServiceWorkerMetrics::EventType::NUM_TYPES:
NOTREACHED() << static_cast<int>(event_type);
}
@@ -227,6 +229,8 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Navigation Hint Link Tap Unconfirmed";
case EventType::NAVIGATION_HINT_LINK_TAP_DOWN:
return "Navigation Hint Link Tap Down";
+ case EventType::EXTERNAL_REQUEST:
+ return "External Request";
case EventType::NUM_TYPES:
break;
}
@@ -565,6 +569,9 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.ExtendableMessageEvent.Time",
time);
break;
+ case EventType::EXTERNAL_REQUEST:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.ExternalRequest.Time", time);
+ break;
// Those navigation hints should not be sent as request events.
case EventType::NAVIGATION_HINT_LINK_MOUSE_DOWN:
case EventType::NAVIGATION_HINT_LINK_TAP_UNCONFIRMED:
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index c57ae0f3343..9f94599399e 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -110,6 +110,9 @@ class ServiceWorkerMetrics {
NAVIGATION_HINT_LINK_MOUSE_DOWN = 18,
NAVIGATION_HINT_LINK_TAP_UNCONFIRMED = 19,
NAVIGATION_HINT_LINK_TAP_DOWN = 20,
+ // Used when external consumers want to add a request to
+ // ServiceWorkerVersion to keep it alive.
+ EXTERNAL_REQUEST = 21,
// Add new events to record here.
NUM_TYPES
};
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.h b/chromium/content/browser/service_worker/service_worker_process_manager.h
index da8443f9fe6..a45fb870155 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.h
@@ -86,12 +86,12 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
bool PatternHasProcessToRun(const GURL& pattern) const;
private:
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP, SortProcess);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
FindAvailableProcess);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
AllocateWorkerProcess_FindAvailableProcess);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
AllocateWorkerProcess_InShutdown);
// Information about the process for an EmbeddedWorkerInstance.
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 aa2d8f670a3..1367d3de2c6 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
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/public/common/child_process_host.h"
#include "content/public/test/mock_render_process_host.h"
@@ -69,7 +70,10 @@ class ServiceWorkerProcessManagerTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProcessManagerTest);
};
-TEST_F(ServiceWorkerProcessManagerTest, SortProcess) {
+class ServiceWorkerProcessManagerTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerProcessManagerTest> {};
+
+TEST_P(ServiceWorkerProcessManagerTestP, SortProcess) {
// Process 1 has 2 refs, 2 has 3 refs and 3 has 1 ref.
process_manager_->AddProcessReferenceToPattern(pattern_, 1);
process_manager_->AddProcessReferenceToPattern(pattern_, 1);
@@ -89,7 +93,7 @@ TEST_F(ServiceWorkerProcessManagerTest, SortProcess) {
testing::ElementsAre(2, 3));
}
-TEST_F(ServiceWorkerProcessManagerTest, FindAvailableProcess) {
+TEST_P(ServiceWorkerProcessManagerTestP, FindAvailableProcess) {
std::unique_ptr<MockRenderProcessHost> host1(CreateRenderProcessHost());
std::unique_ptr<MockRenderProcessHost> host2(CreateRenderProcessHost());
std::unique_ptr<MockRenderProcessHost> host3(CreateRenderProcessHost());
@@ -121,7 +125,7 @@ TEST_F(ServiceWorkerProcessManagerTest, FindAvailableProcess) {
EXPECT_EQ(host3->GetID(), process_manager_->FindAvailableProcess(pattern_));
}
-TEST_F(ServiceWorkerProcessManagerTest,
+TEST_P(ServiceWorkerProcessManagerTestP,
AllocateWorkerProcess_FindAvailableProcess) {
const int kEmbeddedWorkerId1 = 100;
const int kEmbeddedWorkerId2 = 200;
@@ -232,7 +236,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_TRUE(instance_info.empty());
}
-TEST_F(ServiceWorkerProcessManagerTest, AllocateWorkerProcess_InShutdown) {
+TEST_P(ServiceWorkerProcessManagerTestP, AllocateWorkerProcess_InShutdown) {
process_manager_->Shutdown();
ASSERT_TRUE(process_manager_->IsShutdown());
@@ -253,4 +257,8 @@ TEST_F(ServiceWorkerProcessManagerTest, AllocateWorkerProcess_InShutdown) {
EXPECT_TRUE(process_manager_->instance_info_.empty());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerProcessManagerTest,
+ ServiceWorkerProcessManagerTestP,
+ testing::Bool());
+
} // 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 b29ea00d5f5..a53f8a3a75f 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -262,7 +262,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void NotifyControllerLost();
private:
- friend class ServiceWorkerProviderHostTest;
+ friend class LinkHeaderServiceWorkerTest;
+ friend class ServiceWorkerProviderHostTestP;
friend class ServiceWorkerWriteToCacheJobTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
@@ -273,19 +274,19 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
Update_ElongatedScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_EmptyScript);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTestP,
DispatchExtendableMessageEvent);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTestP,
DispatchExtendableMessageEvent_Fail);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateBefore24Hours);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateAfter24Hours);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateForceBypassCache);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
ServiceWorkerDataRequestAnnotation);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTest, ContextSecurity);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTestP, ContextSecurity);
struct OneShotGetReadyCallback {
GetRegistrationForReadyCallback callback;
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 8e5591f12a9..184d661b655 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
@@ -12,6 +12,7 @@
#include "content/browser/service_worker/service_worker_context_core.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/public/common/origin_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -101,7 +102,10 @@ class ServiceWorkerProviderHostTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest);
};
-TEST_F(ServiceWorkerProviderHostTest, PotentialRegistration_ProcessStatus) {
+class ServiceWorkerProviderHostTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerProviderHostTest> {};
+
+TEST_P(ServiceWorkerProviderHostTestP, PotentialRegistration_ProcessStatus) {
// Matching registrations have already been set by SetDocumentUrl.
ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern()));
@@ -130,7 +134,7 @@ TEST_F(ServiceWorkerProviderHostTest, PotentialRegistration_ProcessStatus) {
ASSERT_TRUE(PatternHasProcessToRun(registration3_->pattern())); // host1,2
}
-TEST_F(ServiceWorkerProviderHostTest, AssociatedRegistration_ProcessStatus) {
+TEST_P(ServiceWorkerProviderHostTestP, AssociatedRegistration_ProcessStatus) {
// Associating the registration will also increase the process refs for
// the registration's pattern.
provider_host1_->AssociateRegistration(registration1_.get(),
@@ -143,7 +147,7 @@ TEST_F(ServiceWorkerProviderHostTest, AssociatedRegistration_ProcessStatus) {
ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern()));
}
-TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) {
+TEST_P(ServiceWorkerProviderHostTestP, MatchRegistration) {
// Match registration should return the longest matching one.
ASSERT_EQ(registration2_, provider_host1_->MatchRegistration());
provider_host1_->RemoveMatchingRegistration(registration2_.get());
@@ -166,7 +170,7 @@ TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) {
ASSERT_EQ(nullptr, provider_host1_->MatchRegistration());
}
-TEST_F(ServiceWorkerProviderHostTest, ContextSecurity) {
+TEST_P(ServiceWorkerProviderHostTestP, ContextSecurity) {
using FrameSecurityLevel = ServiceWorkerProviderHost::FrameSecurityLevel;
content::ResetSchemesAndOriginsWhitelistForTesting();
@@ -199,4 +203,8 @@ TEST_F(ServiceWorkerProviderHostTest, ContextSecurity) {
EXPECT_FALSE(provider_host1_->IsContextSecureForServiceWorker());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerProviderHostTest,
+ ServiceWorkerProviderHostTestP,
+ ::testing::Values(false, true));
+
} // 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 24f84342fed..a93bf74035a 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
@@ -164,8 +164,11 @@ void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) {
if (is_range_request())
SetupRangeResponse(http_info_io_buffer_->response_data_size);
http_info_io_buffer_ = nullptr;
- if (request_->url() == version_->script_url())
+ if (is_main_script()) {
+ // TODO(nhiroki): Temporary check for debugging (https://crbug.com/485900).
+ CHECK_EQ(request_->url(), version_->script_url());
version_->SetMainScriptHttpResponseInfo(*http_info_);
+ }
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerReadFromCacheJob::ReadInfo",
this,
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index b903a386a0d..852c7a27e32 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -15,6 +15,7 @@
#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_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
@@ -188,7 +189,10 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
MockURLRequestDelegate delegate_;
};
-TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
+class ServiceWorkerReadFromCacheJobTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerReadFromCacheJobTest> {};
+
+TEST_P(ServiceWorkerReadFromCacheJobTestP, ReadMainScript) {
// Read the main script from the diskcache.
std::unique_ptr<net::URLRequest> request =
url_request_context_->CreateRequest(main_script_.url,
@@ -206,7 +210,7 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
}
-TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
+TEST_P(ServiceWorkerReadFromCacheJobTestP, ReadImportedScript) {
// Read the imported script from the diskcache.
std::unique_ptr<net::URLRequest> request =
url_request_context_->CreateRequest(imported_script_.url,
@@ -223,7 +227,7 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
}
-TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
+TEST_P(ServiceWorkerReadFromCacheJobTestP, ResourceNotFound) {
ASSERT_EQ(SERVICE_WORKER_OK, FindRegistration());
// Try to read a nonexistent resource from the diskcache.
@@ -249,4 +253,8 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, FindRegistration());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerReadFromCacheJobTest,
+ ServiceWorkerReadFromCacheJobTestP,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.h b/chromium/content/browser/service_worker/service_worker_register_job.h
index 5f93fd351fa..4fff29b8c55 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -19,9 +19,6 @@
namespace content {
-class ServiceWorkerJobCoordinator;
-class ServiceWorkerStorage;
-
// Handles the initial registration of a Service Worker and the
// subsequent update of existing registrations.
//
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index ef587ee2a6b..1612f26e629 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -48,11 +48,6 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(
}
ServiceWorkerRegistration::~ServiceWorkerRegistration() {
- // Can be false during shutdown, in which case the DCHECK_CURRENTLY_ON below
- // would cry.
- if (!BrowserThread::IsThreadInitialized(BrowserThread::IO))
- return;
-
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!listeners_.might_have_observers());
if (context_)
@@ -78,18 +73,20 @@ void ServiceWorkerRegistration::RemoveListener(Listener* listener) {
}
void ServiceWorkerRegistration::NotifyRegistrationFailed() {
- FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this));
+ for (auto& observer : listeners_)
+ observer.OnRegistrationFailed(this);
NotifyRegistrationFinished();
}
void ServiceWorkerRegistration::NotifyUpdateFound() {
- FOR_EACH_OBSERVER(Listener, listeners_, OnUpdateFound(this));
+ for (auto& observer : listeners_)
+ observer.OnUpdateFound(this);
}
void ServiceWorkerRegistration::NotifyVersionAttributesChanged(
ChangedVersionAttributesMask mask) {
- FOR_EACH_OBSERVER(Listener, listeners_,
- OnVersionAttributesChanged(this, mask, GetInfo()));
+ for (auto& observer : listeners_)
+ observer.OnVersionAttributesChanged(this, mask, GetInfo());
if (mask.active_changed() || mask.waiting_changed())
NotifyRegistrationFinished();
}
@@ -118,8 +115,10 @@ void ServiceWorkerRegistration::SetActiveVersion(
if (active_version_)
active_version_->RemoveListener(this);
active_version_ = version;
- if (active_version_)
+ if (active_version_) {
active_version_->AddListener(this);
+ active_version_->SetNavigationPreloadState(navigation_preload_state_);
+ }
mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
NotifyVersionAttributesChanged(mask);
@@ -314,8 +313,10 @@ void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) {
// "activating" as arguments."
activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING);
// "9. Fire a simple event named controllerchange..."
- if (activating_version->skip_waiting())
- FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
+ if (activating_version->skip_waiting()) {
+ for (auto& observer : listeners_)
+ observer.OnSkippedWaiting(this);
+ }
// "10. Queue a task to fire an event named activate..."
// The browser could be shutting down. To avoid spurious start worker
@@ -390,6 +391,23 @@ void ServiceWorkerRegistration::SetTaskRunnerForTest(
task_runner_ = task_runner;
}
+void ServiceWorkerRegistration::EnableNavigationPreload(bool enable) {
+ if (navigation_preload_state_.enabled == enable)
+ return;
+ navigation_preload_state_.enabled = enable;
+ if (active_version_)
+ active_version_->SetNavigationPreloadState(navigation_preload_state_);
+}
+
+void ServiceWorkerRegistration::SetNavigationPreloadHeader(
+ const std::string& header) {
+ if (navigation_preload_state_.header == header)
+ return;
+ navigation_preload_state_.header = header;
+ if (active_version_)
+ active_version_->SetNavigationPreloadState(navigation_preload_state_);
+}
+
void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
const base::Closure& callback) {
// This should only be called if the registration is in progress.
@@ -488,8 +506,8 @@ void ServiceWorkerRegistration::Clear() {
version->Doom();
}
- FOR_EACH_OBSERVER(
- Listener, listeners_, OnRegistrationFinishedUninstalling(this));
+ for (auto& observer : listeners_)
+ observer.OnRegistrationFinishedUninstalling(this);
}
void ServiceWorkerRegistration::OnRestoreFinished(
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index 8a69821a962..0efc111087c 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -95,6 +95,14 @@ class CONTENT_EXPORT ServiceWorkerRegistration
return active_version() || waiting_version();
}
+ bool is_navigation_preload_enabled() const {
+ return navigation_preload_state_.enabled;
+ }
+
+ const std::string& navigation_preload_header() const {
+ return navigation_preload_state_.header;
+ }
+
ServiceWorkerVersion* GetNewestVersion() const;
void AddListener(Listener* listener);
@@ -150,6 +158,9 @@ class CONTENT_EXPORT ServiceWorkerRegistration
void SetTaskRunnerForTest(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ void EnableNavigationPreload(bool enable);
+ void SetNavigationPreloadHeader(const std::string& value);
+
private:
friend class base::RefCounted<ServiceWorkerRegistration>;
@@ -192,6 +203,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
bool is_uninstalling_;
bool is_uninstalled_;
bool should_activate_when_ready_;
+ NavigationPreloadState navigation_preload_state_;
base::Time last_update_check_;
int64_t resources_total_size_bytes_;
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 9ddd0c57de0..e06b112e1f4 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_handle.h
@@ -17,7 +17,6 @@
namespace content {
class ServiceWorkerContextCore;
-class ServiceWorkerDispatcherHost;
class ServiceWorkerVersion;
// Roughly corresponds to one WebServiceWorkerRegistration object in the
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 494240c3feb..b9113b2de32 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -99,7 +99,10 @@ class ServiceWorkerRegistrationTest : public testing::Test {
TestBrowserThreadBundle thread_bundle_;
};
-TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
+class ServiceWorkerRegistrationTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerRegistrationTest> {};
+
+TEST_P(ServiceWorkerRegistrationTestP, SetAndUnsetVersions) {
const GURL kScope("http://www.example.not/");
const GURL kScript("http://www.example.not/service_worker.js");
int64_t kRegistrationId = 1L;
@@ -167,7 +170,7 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
kInvalidServiceWorkerVersionId);
}
-TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
+TEST_P(ServiceWorkerRegistrationTestP, FailedRegistrationNoCrash) {
const GURL kScope("http://www.example.not/");
int64_t kRegistrationId = 1L;
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -181,11 +184,47 @@ TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
// Don't crash when handle gets destructed.
}
+TEST_P(ServiceWorkerRegistrationTestP, NavigationPreload) {
+ const GURL kScope("http://www.example.not/");
+ const GURL kScript("https://www.example.not/service_worker.js");
+ // Setup.
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(kScope, storage()->NewRegistrationId(),
+ context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion(
+ registration.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ version_1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ registration->SetActiveVersion(version_1);
+ version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion(
+ registration.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ version_2->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ registration->SetWaitingVersion(version_2);
+ version_2->SetStatus(ServiceWorkerVersion::INSTALLED);
+
+ // Navigation preload is disabled by default.
+ EXPECT_FALSE(version_1->navigation_preload_state().enabled);
+ // Enabling it sets the flag on the active version.
+ registration->EnableNavigationPreload(true);
+ EXPECT_TRUE(version_1->navigation_preload_state().enabled);
+ // A new active version gets the flag.
+ registration->SetActiveVersion(version_2);
+ version_2->SetStatus(ServiceWorkerVersion::ACTIVATING);
+ EXPECT_TRUE(version_2->navigation_preload_state().enabled);
+ // Disabling it unsets the flag on the active version.
+ registration->EnableNavigationPreload(false);
+ EXPECT_FALSE(version_2->navigation_preload_state().enabled);
+}
+
// Sets up a registration with a waiting worker, and an active worker
// with a controllee and an inflight request.
-class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTestP {
public:
- ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
+ ServiceWorkerActivationTest() : ServiceWorkerRegistrationTestP() {}
void SetUp() override {
ServiceWorkerRegistrationTest::SetUp();
@@ -261,7 +300,7 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
};
// Test activation triggered by finishing all requests.
-TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
+TEST_P(ServiceWorkerActivationTest, NoInflightRequest) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -280,7 +319,7 @@ TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
}
// Test activation triggered by loss of controllee.
-TEST_F(ServiceWorkerActivationTest, NoControllee) {
+TEST_P(ServiceWorkerActivationTest, NoControllee) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -299,7 +338,7 @@ TEST_F(ServiceWorkerActivationTest, NoControllee) {
}
// Test activation triggered by skipWaiting.
-TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
+TEST_P(ServiceWorkerActivationTest, SkipWaiting) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -318,7 +357,7 @@ TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
}
// Test activation triggered by skipWaiting and finishing requests.
-TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
+TEST_P(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -336,4 +375,12 @@ TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
EXPECT_EQ(version_2.get(), reg->active_version());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerRegistrationTest,
+ ServiceWorkerRegistrationTestP,
+ testing::Bool());
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerActivationTest,
+ ServiceWorkerActivationTest,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.h b/chromium/content/browser/service_worker/service_worker_request_handler.h
index 947f3bbed88..f264db951ed 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -32,7 +32,6 @@ class BlobStorageContext;
namespace content {
class ResourceContext;
-class ResourceMessageFilter;
class ResourceRequestBodyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
index aaab37f7a33..414f01b33e5 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -12,6 +12,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_test_utils.h"
#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/request_context_frame_type.h"
@@ -116,7 +117,10 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
storage::BlobStorageContext blob_storage_context_;
};
-TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler) {
+class ServiceWorkerRequestHandlerTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerRequestHandlerTest> {};
+
+TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler) {
// Cannot initialize a handler for non-secure origins.
EXPECT_FALSE(InitializeHandlerCheck(
"ftp://host/scope/doc", "GET", false, RESOURCE_TYPE_MAIN_FRAME));
@@ -163,4 +167,8 @@ TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler) {
EXPECT_STREQ("", provider_host_->document_url().spec().c_str());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerRequestHandlerTest,
+ ServiceWorkerRequestHandlerTestP,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index e5713ad6234..b6e9e2f59bd 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -408,6 +408,8 @@ void ServiceWorkerStorage::StoreRegistration(
data.is_active = (version == registration->active_version());
data.foreign_fetch_scopes = version->foreign_fetch_scopes();
data.foreign_fetch_origins = version->foreign_fetch_origins();
+ if (version->origin_trial_tokens())
+ data.origin_trial_tokens = *version->origin_trial_tokens();
ResourceList resources;
version->script_cache_map()->GetResources(&resources);
@@ -1260,6 +1262,8 @@ ServiceWorkerStorage::GetOrCreateRegistration(
version->script_cache_map()->SetResources(resources);
version->set_foreign_fetch_scopes(data.foreign_fetch_scopes);
version->set_foreign_fetch_origins(data.foreign_fetch_origins);
+ if (data.origin_trial_tokens)
+ version->SetValidOriginTrialTokens(*data.origin_trial_tokens);
}
if (version->status() == ServiceWorkerVersion::ACTIVATED)
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 9e7d267cfaa..fcdc0d64670 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -232,6 +232,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
friend class ServiceWorkerDispatcherHostTest;
friend class ServiceWorkerHandleTest;
friend class ServiceWorkerStorageTest;
+ friend class ServiceWorkerStorageOriginTrialsTest;
friend class ServiceWorkerRegistrationTest;
friend class ServiceWorkerResourceStorageTest;
friend class ServiceWorkerControlleeRequestHandlerTest;
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 1e57b5cb5e4..ac487fd24ef 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -20,15 +20,21 @@
#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_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_status_code.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/origin_trial_policy.h"
#include "content/public/test/test_browser_thread_bundle.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/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::IOBuffer;
@@ -42,6 +48,21 @@ namespace {
typedef ServiceWorkerDatabase::RegistrationData RegistrationData;
typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord;
+// This is a sample public key for testing the API. The corresponding private
+// key (use this to generate new samples for this test file) is:
+//
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
+// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
+// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
+// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
+const uint8_t kTestPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+
void StatusAndQuitCallback(ServiceWorkerStatusCode* result,
const base::Closure& quit_closure,
ServiceWorkerStatusCode status) {
@@ -509,7 +530,10 @@ class ServiceWorkerStorageTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
};
-TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
+class ServiceWorkerStorageTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerStorageTest> {};
+
+TEST_P(ServiceWorkerStorageTestP, DisabledStorage) {
const GURL kScope("http://www.example.com/scope/");
const GURL kScript("http://www.example.com/script.js");
const GURL kDocumentUrl("http://www.example.com/scope/document.html");
@@ -587,7 +611,7 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
EXPECT_EQ(kInvalidServiceWorkerResourceId, storage()->NewRegistrationId());
}
-TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
+TEST_P(ServiceWorkerStorageTestP, StoreFindUpdateDeleteRegistration) {
const GURL kScope("http://www.test.not/scope/");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
const GURL kResource1("http://www.test.not/scope/resource1.js");
@@ -789,7 +813,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
}
-TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
+TEST_P(ServiceWorkerStorageTestP, InstallingRegistrationsAreFindable) {
const GURL kScope("http://www.test.not/scope/");
const GURL kScript("http://www.test.not/script.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
@@ -918,7 +942,7 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
EXPECT_TRUE(registrations_for_origin.empty());
}
-TEST_F(ServiceWorkerStorageTest, StoreUserData) {
+TEST_P(ServiceWorkerStorageTestP, StoreUserData) {
const GURL kScope("http://www.test.not/scope/");
const GURL kScript("http://www.test.not/script.js");
const int64_t kRegistrationId = 0;
@@ -1057,10 +1081,10 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
GetUserDataForAllRegistrations(std::string(), &data_list_out));
}
-class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
+class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTestP {
public:
void SetUp() override {
- ServiceWorkerStorageTest::SetUp();
+ ServiceWorkerStorageTestP::SetUp();
LazyInitialize();
scope_ = GURL("http://www.test.not/scope/");
@@ -1139,7 +1163,7 @@ class ServiceWorkerResourceStorageDiskTest
};
-TEST_F(ServiceWorkerResourceStorageTest,
+TEST_P(ServiceWorkerResourceStorageTest,
WriteMetadataWithServiceWorkerResponseMetadataWriter) {
const char kMetadata1[] = "Test metadata";
const char kMetadata2[] = "small";
@@ -1165,7 +1189,7 @@ TEST_F(ServiceWorkerResourceStorageTest,
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
}
-TEST_F(ServiceWorkerResourceStorageTest,
+TEST_P(ServiceWorkerResourceStorageTest,
WriteMetadataWithServiceWorkerScriptCacheMap) {
const char kMetadata1[] = "Test metadata";
const char kMetadata2[] = "small";
@@ -1198,7 +1222,7 @@ TEST_F(ServiceWorkerResourceStorageTest,
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
}
-TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
+TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
std::set<int64_t> verify_ids;
@@ -1230,7 +1254,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
-TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
+TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
std::set<int64_t> verify_ids;
@@ -1272,7 +1296,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
-TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
+TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
// Promote the worker to active and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
storage()->UpdateToActiveState(
@@ -1323,7 +1347,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
-TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
+TEST_P(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
// Promote the worker to active and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
registration_->SetWaitingVersion(NULL);
@@ -1408,7 +1432,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
}
-TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
+TEST_P(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
EXPECT_FALSE(storage()->IsDisabled());
ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
@@ -1425,7 +1449,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
}
-TEST_F(ServiceWorkerResourceStorageDiskTest,
+TEST_P(ServiceWorkerResourceStorageDiskTest,
DeleteAndStartOver_UnrelatedFileExists) {
EXPECT_FALSE(storage()->IsDisabled());
ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
@@ -1450,7 +1474,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
}
-TEST_F(ServiceWorkerResourceStorageDiskTest,
+TEST_P(ServiceWorkerResourceStorageDiskTest,
DeleteAndStartOver_OpenedFileExists) {
EXPECT_FALSE(storage()->IsDisabled());
ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
@@ -1484,7 +1508,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
#endif
}
-TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
+TEST_P(ServiceWorkerResourceStorageTest, UpdateRegistration) {
// Promote the worker to active worker and add a controllee.
registration_->SetActiveVersion(registration_->waiting_version());
storage()->UpdateToActiveState(
@@ -1549,7 +1573,7 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
-TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
+TEST_P(ServiceWorkerStorageTestP, FindRegistration_LongestScopeMatch) {
const GURL kDocumentUrl("http://www.example.com/scope/foo");
scoped_refptr<ServiceWorkerRegistration> found_registration;
@@ -1643,15 +1667,15 @@ TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
EXPECT_EQ(live_registration2, found_registration);
}
-class ServiceWorkerStorageDiskTest : public ServiceWorkerStorageTest {
+class ServiceWorkerStorageDiskTest : public ServiceWorkerStorageTestP {
public:
void SetUp() override {
ASSERT_TRUE(InitUserDataDirectory());
- ServiceWorkerStorageTest::SetUp();
+ ServiceWorkerStorageTestP::SetUp();
}
};
-TEST_F(ServiceWorkerStorageDiskTest, OriginHasForeignFetchRegistrations) {
+TEST_P(ServiceWorkerStorageDiskTest, OriginHasForeignFetchRegistrations) {
LazyInitialize();
// Registration 1 for http://www.example.com
@@ -1762,4 +1786,223 @@ TEST_F(ServiceWorkerStorageDiskTest, OriginHasForeignFetchRegistrations) {
EXPECT_FALSE(storage()->OriginHasForeignFetchRegistrations(kOrigin2));
}
+class ServiceWorkerStorageOriginTrialsTest : public ServiceWorkerStorageTestP {
+ public:
+ ServiceWorkerStorageOriginTrialsTest() {}
+ ~ServiceWorkerStorageOriginTrialsTest() override {}
+
+ protected:
+ void WriteRegistration(const RegistrationData& registration,
+ const std::vector<ResourceRecord>& resources) {
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ std::vector<int64_t> newly_purgeable_resources;
+
+ ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->WriteRegistration(
+ registration, resources, &deleted_version,
+ &newly_purgeable_resources));
+ }
+};
+
+TEST_P(ServiceWorkerStorageOriginTrialsTest, AbsentEntryAndEmptyEntry) {
+ const GURL origin1("http://www1.example.com");
+ const GURL scope1("http://www1.example.com/foo/");
+ RegistrationData data1;
+ data1.registration_id = 100;
+ data1.scope = scope1;
+ data1.script = GURL(origin1.spec() + "/script.js");
+ data1.version_id = 1000;
+ data1.is_active = true;
+ data1.resources_total_size_bytes = 100;
+ // Don't set origin_trial_tokens to simulate old database entry.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources1;
+ resources1.push_back(
+ ServiceWorkerDatabase::ResourceRecord(1, data1.script, 100));
+ WriteRegistration(data1, resources1);
+
+ const GURL origin2("http://www2.example.com");
+ const GURL scope2("http://www2.example.com/foo/");
+ RegistrationData data2;
+ data2.registration_id = 200;
+ data2.scope = scope2;
+ data2.script = GURL(origin2.spec() + "/script.js");
+ data2.version_id = 2000;
+ data2.is_active = true;
+ data2.resources_total_size_bytes = 200;
+ // Set empty origin_trial_tokens.
+ data2.origin_trial_tokens = TrialTokenValidator::FeatureToTokensMap();
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources2;
+ resources2.push_back(
+ ServiceWorkerDatabase::ResourceRecord(2, data2.script, 200));
+ WriteRegistration(data2, resources2);
+
+ scoped_refptr<ServiceWorkerRegistration> found_registration;
+
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ FindRegistrationForDocument(scope1, &found_registration));
+ ASSERT_TRUE(found_registration->active_version());
+ // origin_trial_tokens must be unset.
+ EXPECT_FALSE(found_registration->active_version()->origin_trial_tokens());
+
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ FindRegistrationForDocument(scope2, &found_registration));
+ ASSERT_TRUE(found_registration->active_version());
+ // Empty origin_trial_tokens must exist.
+ ASSERT_TRUE(found_registration->active_version()->origin_trial_tokens());
+ EXPECT_TRUE(
+ found_registration->active_version()->origin_trial_tokens()->empty());
+}
+
+class ServiceWorkerStorageOriginTrialsDiskTest
+ : public ServiceWorkerStorageTestP {
+ public:
+ ServiceWorkerStorageOriginTrialsDiskTest() {
+ SetContentClient(&test_content_client_);
+ }
+ ~ServiceWorkerStorageOriginTrialsDiskTest() override {
+ SetContentClient(nullptr);
+ }
+ void SetUp() override {
+ ASSERT_TRUE(InitUserDataDirectory());
+ ServiceWorkerStorageTestP::SetUp();
+ }
+
+ private:
+ class TestOriginTrialPolicy : public OriginTrialPolicy {
+ public:
+ base::StringPiece GetPublicKey() const override {
+ return base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
+ arraysize(kTestPublicKey));
+ }
+ bool IsFeatureDisabled(base::StringPiece feature) const override {
+ return false;
+ }
+ };
+ class TestContentClient : public ContentClient {
+ public:
+ // ContentRendererClient methods
+ OriginTrialPolicy* GetOriginTrialPolicy() override {
+ return &origin_trial_policy_;
+ }
+
+ private:
+ TestOriginTrialPolicy origin_trial_policy_;
+ };
+ TestContentClient test_content_client_;
+};
+
+TEST_P(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
+ LazyInitialize();
+ const GURL kScope("https://valid.example.com/scope");
+ const GURL kScript("https://valid.example.com/script.js");
+ const int64_t kRegistrationId = 1;
+ const int64_t kVersionId = 1;
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(kScope, kRegistrationId,
+ context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
+ registration.get(), kScript, kVersionId, context()->AsWeakPtr());
+
+ 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;
+
+ const std::string kHTTPHeaderLine("HTTP/1.1 200 OK\n\n");
+ const std::string kOriginTrial("Origin-Trial: ");
+ // Token for Feature1 which expires 2033-05-18.
+ // generate_token.py valid.example.com Feature1 --expire-timestamp=2000000000
+ // TODO(horo): Generate this sample token during the build.
+ const std::string kFeature1Token(
+ "AtiUXksymWhTv5ipBE7853JytiYb0RMj3wtEBjqu3PeufQPwV1oEaNjHt4R/oEBfcK0UiWlA"
+ "P2b9BE2/eThqcAYAAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMSIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==");
+ // Token for Feature2 which expires 2033-05-18.
+ // generate_token.py valid.example.com Feature2 --expire-timestamp=2000000000
+ // TODO(horo): Generate this sample token during the build.
+ const std::string kFeature2Token1(
+ "ApmHVC6Dpez0KQNBy13o6cGuoB5AgzOLN0keQMyAN5mjebCwR0MA8/IyjKQIlyom2RuJVg/u"
+ "LmnqEpldfewkbA8AAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMiIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==");
+ // Token for Feature2 which expires 2036-07-18.
+ // generate_token.py valid.example.com Feature2 --expire-timestamp=2100000000
+ // TODO(horo): Generate this sample token during the build.
+ const std::string kFeature2Token2(
+ "AmV2SSxrYstE2zSwZToy7brAbIJakd146apC/6+VDflLmc5yDfJlHGILe5+ZynlcliG7clOR"
+ "fHhXCzS5Lh1v4AAAAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMiIsICJleHBpcnkiOiAyMTAwMDAwMDAwfQ==");
+ // Token for Feature3 which expired 2001-09-09.
+ // generate_token.py valid.example.com Feature3 --expire-timestamp=1000000000
+ const std::string kFeature3ExpiredToken(
+ "AtSAc03z4qvid34W4MHMxyRFUJKlubZ+P5cs5yg6EiBWcagVbnm5uBgJMJN34pag7D5RywGV"
+ "ol2RFf+4Sdm1hQ4AAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
+ "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMyIsICJleHBpcnkiOiAxMDAwMDAwMDAwfQ==");
+ http_info.headers = make_scoped_refptr(new net::HttpResponseHeaders(""));
+ http_info.headers->AddHeader(kOriginTrial + kFeature1Token);
+ http_info.headers->AddHeader(kOriginTrial + kFeature2Token1);
+ http_info.headers->AddHeader(kOriginTrial + kFeature2Token2);
+ http_info.headers->AddHeader(kOriginTrial + kFeature3ExpiredToken);
+ version->SetMainScriptHttpResponseInfo(http_info);
+ ASSERT_TRUE(version->origin_trial_tokens());
+ const TrialTokenValidator::FeatureToTokensMap& tokens =
+ *version->origin_trial_tokens();
+ ASSERT_EQ(2UL, tokens.size());
+ ASSERT_EQ(1UL, tokens.at("Feature1").size());
+ EXPECT_EQ(kFeature1Token, tokens.at("Feature1")[0]);
+ ASSERT_EQ(2UL, tokens.at("Feature2").size());
+ EXPECT_EQ(kFeature2Token1, tokens.at("Feature2")[0]);
+ EXPECT_EQ(kFeature2Token2, tokens.at("Feature2")[1]);
+
+ std::vector<ServiceWorkerDatabase::ResourceRecord> record;
+ record.push_back(ServiceWorkerDatabase::ResourceRecord(1, kScript, 100));
+ version->script_cache_map()->SetResources(record);
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version->SetStatus(ServiceWorkerVersion::INSTALLED);
+ registration->SetActiveVersion(version);
+
+ EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(registration, version));
+
+ // Simulate browser shutdown and restart.
+ registration = nullptr;
+ version = nullptr;
+ InitializeTestHelper();
+ LazyInitialize();
+
+ scoped_refptr<ServiceWorkerRegistration> found_registration;
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ FindRegistrationForDocument(kScope, &found_registration));
+ ASSERT_TRUE(found_registration->active_version());
+ const TrialTokenValidator::FeatureToTokensMap& found_tokens =
+ *found_registration->active_version()->origin_trial_tokens();
+ ASSERT_EQ(2UL, found_tokens.size());
+ ASSERT_EQ(1UL, found_tokens.at("Feature1").size());
+ EXPECT_EQ(kFeature1Token, found_tokens.at("Feature1")[0]);
+ ASSERT_EQ(2UL, found_tokens.at("Feature2").size());
+ EXPECT_EQ(kFeature2Token1, found_tokens.at("Feature2")[0]);
+ EXPECT_EQ(kFeature2Token2, found_tokens.at("Feature2")[1]);
+}
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerResourceStorageDiskTest,
+ ServiceWorkerResourceStorageDiskTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerResourceStorageTest,
+ ServiceWorkerResourceStorageTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageDiskTest,
+ ServiceWorkerStorageDiskTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageOriginTrialsDiskTest,
+ ServiceWorkerStorageOriginTrialsDiskTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageOriginTrialsTest,
+ ServiceWorkerStorageOriginTrialsTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageTestP,
+ ServiceWorkerStorageTestP,
+ testing::Bool());
+
} // 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 9e3983baa59..8aa67edbb47 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.h
@@ -7,10 +7,28 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/command_line.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace content {
+template <class TestClass>
+class MojoServiceWorkerTestP : public TestClass,
+ public testing::WithParamInterface<bool> {
+ protected:
+ void SetUp() override {
+ if (!is_mojo_enabled()) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableMojoServiceWorker);
+ }
+ TestClass::SetUp();
+ }
+
+ bool is_mojo_enabled() const { return GetParam(); }
+};
+
template <typename Arg>
void ReceiveResult(BrowserThread::ID run_quit_thread,
const base::Closure& quit,
diff --git a/chromium/content/browser/service_worker/service_worker_unregister_job.h b/chromium/content/browser/service_worker/service_worker_unregister_job.h
index 517bc27b0af..11964d5fece 100644
--- a/chromium/content/browser/service_worker/service_worker_unregister_job.h
+++ b/chromium/content/browser/service_worker/service_worker_unregister_job.h
@@ -17,11 +17,8 @@
namespace content {
-class EmbeddedWorkerRegistry;
class ServiceWorkerContextCore;
-class ServiceWorkerJobCoordinator;
class ServiceWorkerRegistration;
-class ServiceWorkerStorage;
// Handles the unregistration of a Service Worker.
//
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 e979fdd1b24..22403a2205c 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
@@ -7,17 +7,22 @@
#include <stddef.h>
#include <stdint.h>
-#include <limits>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/files/file_util.h"
#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/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/resource_context_impl.h"
@@ -31,6 +36,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/blob_handle.h"
+#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/referrer.h"
@@ -104,90 +110,109 @@ net::NetLogEventType RequestJobResultToNetEventType(
return n::FAILED;
}
+std::vector<int64_t> GetFileSizesOnBlockingPool(
+ std::vector<base::FilePath> file_paths) {
+ std::vector<int64_t> sizes;
+ sizes.reserve(file_paths.size());
+ for (const base::FilePath& path : file_paths) {
+ base::File::Info file_info;
+ if (!base::GetFileInfo(path, &file_info) || file_info.is_directory)
+ return std::vector<int64_t>();
+ sizes.push_back(file_info.size);
+ }
+ return sizes;
+}
+
} // namespace
-class ServiceWorkerURLRequestJob::BlobConstructionWaiter {
+// Sets the size on each DataElement in the request body that is a file with
+// unknown size. This ensures ServiceWorkerURLRequestJob::CreateRequestBodyBlob
+// can successfuly create a blob from the data elements, as files with unknown
+// sizes are not supported by the blob storage system.
+class ServiceWorkerURLRequestJob::FileSizeResolver {
public:
- explicit BlobConstructionWaiter(ServiceWorkerURLRequestJob* owner)
+ explicit FileSizeResolver(ServiceWorkerURLRequestJob* owner)
: owner_(owner), weak_factory_(this) {
- TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "BlobConstructionWaiter", this,
- "URL", owner_->request()->url().spec());
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "FileSizeResolver", this, "URL",
+ owner_->request()->url().spec());
owner_->request()->net_log().BeginEvent(
- net::NetLogEventType::SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_BLOB);
+ net::NetLogEventType::SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_FILES);
}
- ~BlobConstructionWaiter() {
+ ~FileSizeResolver() {
owner_->request()->net_log().EndEvent(
- net::NetLogEventType::SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_BLOB,
+ net::NetLogEventType::SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_FILES,
net::NetLog::BoolCallback("success", phase_ == Phase::SUCCESS));
- TRACE_EVENT_ASYNC_END1("ServiceWorker", "BlobConstructionWaiter", this,
- "Success", phase_ == Phase::SUCCESS);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "FileSizeResolver", this, "Success",
+ phase_ == Phase::SUCCESS);
}
- void RunOnComplete(const base::Callback<void(bool)>& callback) {
+ void Resolve(base::TaskRunner* file_runner,
+ const base::Callback<void(bool)>& callback) {
DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_));
+ DCHECK(file_elements_.empty());
phase_ = Phase::WAITING;
- num_pending_request_body_blobs_ = 0;
+ body_ = owner_->body_;
callback_ = callback;
- for (const ResourceRequestBodyImpl::Element& element :
- *(owner_->body_->elements())) {
- if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB)
- continue;
-
- std::unique_ptr<storage::BlobDataHandle> handle =
- owner_->blob_storage_context_->GetBlobDataFromUUID(
- element.blob_uuid());
- if (handle->IsBroken()) {
- Complete(false);
- return;
- }
- if (handle->IsBeingBuilt()) {
- ++num_pending_request_body_blobs_;
- handle->RunOnConstructionComplete(
- base::Bind(&BlobConstructionWaiter::OneRequestBodyBlobCompleted,
- weak_factory_.GetWeakPtr()));
+ std::vector<base::FilePath> file_paths;
+ for (ResourceRequestBodyImpl::Element& element :
+ *body_->elements_mutable()) {
+ if (element.type() == ResourceRequestBodyImpl::Element::TYPE_FILE &&
+ element.length() == ResourceRequestBodyImpl::Element::kUnknownSize) {
+ file_elements_.push_back(&element);
+ file_paths.push_back(element.path());
}
}
-
- if (num_pending_request_body_blobs_ == 0)
+ if (file_elements_.empty()) {
Complete(true);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ file_runner, FROM_HERE,
+ base::Bind(&GetFileSizesOnBlockingPool, base::Passed(&file_paths)),
+ base::Bind(
+ &ServiceWorkerURLRequestJob::FileSizeResolver::OnFileSizesResolved,
+ weak_factory_.GetWeakPtr()));
}
private:
enum class Phase { INITIAL, WAITING, SUCCESS, FAIL };
- void OneRequestBodyBlobCompleted(
- bool success,
- storage::IPCBlobCreationCancelCode cancel_code) {
- DCHECK_GT(num_pending_request_body_blobs_, 0UL);
-
- if (success)
- --num_pending_request_body_blobs_;
- else
- num_pending_request_body_blobs_ = 0;
-
- if (num_pending_request_body_blobs_ == 0)
- Complete(success);
+ void OnFileSizesResolved(std::vector<int64_t> sizes) {
+ bool success = !sizes.empty();
+ if (success) {
+ DCHECK_EQ(sizes.size(), file_elements_.size());
+ size_t num_elements = file_elements_.size();
+ for (size_t i = 0; i < num_elements; i++) {
+ ResourceRequestBodyImpl::Element* element = file_elements_[i];
+ element->SetToFilePathRange(element->path(), element->offset(),
+ base::checked_cast<uint64_t>(sizes[i]),
+ element->expected_modification_time());
+ }
+ file_elements_.clear();
+ }
+ Complete(success);
}
void Complete(bool success) {
DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_));
phase_ = success ? Phase::SUCCESS : Phase::FAIL;
- // Destroys |this|.
- callback_.Run(success);
+ // Destroys |this|, so we use a copy.
+ base::ResetAndReturn(&callback_).Run(success);
}
// Owns and must outlive |this|.
ServiceWorkerURLRequestJob* owner_;
scoped_refptr<ResourceRequestBodyImpl> body_;
+ std::vector<ResourceRequestBodyImpl::Element*> file_elements_;
base::Callback<void(bool)> callback_;
- size_t num_pending_request_body_blobs_ = 0;
Phase phase_ = Phase::INITIAL;
- base::WeakPtrFactory<BlobConstructionWaiter> weak_factory_;
+ base::WeakPtrFactory<FileSizeResolver> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(BlobConstructionWaiter);
+ DISALLOW_COPY_AND_ASSIGN(FileSizeResolver);
};
bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid(
@@ -233,7 +258,7 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
stream_reader_.reset();
- blob_construction_waiter_.reset();
+ file_size_resolver_.reset();
if (!ShouldRecordResult())
return;
@@ -366,9 +391,7 @@ void ServiceWorkerURLRequestJob::RecordResult(
}
did_record_result_ = true;
ServiceWorkerMetrics::RecordURLRequestJobResult(IsMainResourceLoad(), result);
- if (request()) {
- request()->net_log().AddEvent(RequestJobResultToNetEventType(result));
- }
+ request()->net_log().AddEvent(RequestJobResultToNetEventType(result));
}
base::WeakPtr<ServiceWorkerURLRequestJob>
@@ -412,15 +435,17 @@ void ServiceWorkerURLRequestJob::StartRequest() {
case FORWARD_TO_SERVICE_WORKER:
if (HasRequestBody()) {
- DCHECK(!blob_construction_waiter_);
- blob_construction_waiter_.reset(new BlobConstructionWaiter(this));
- blob_construction_waiter_->RunOnComplete(
- base::Bind(&ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted,
- GetWeakPtr()));
+ DCHECK(!file_size_resolver_);
+ file_size_resolver_.reset(new FileSizeResolver(this));
+ file_size_resolver_->Resolve(
+ BrowserThread::GetBlockingPool(),
+ base::Bind(
+ &ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved,
+ GetWeakPtr()));
return;
}
- RequestBodyBlobsCompleted(true);
+ RequestBodyFileSizesResolved(true);
return;
}
@@ -472,70 +497,15 @@ ServiceWorkerURLRequestJob::CreateFetchRequest() {
void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
uint64_t* blob_size) {
DCHECK(HasRequestBody());
- // To ensure the blobs stick around until the end of the reading.
- std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
- std::vector<std::unique_ptr<storage::BlobDataSnapshot>> snapshots;
- // TODO(dmurph): Allow blobs to be added below, so that the context can
- // efficiently re-use blob items for the new blob.
- std::vector<const ResourceRequestBodyImpl::Element*> resolved_elements;
+ storage::BlobDataBuilder blob_builder(base::GenerateGUID());
for (const ResourceRequestBodyImpl::Element& element : (*body_->elements())) {
- if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB) {
- resolved_elements.push_back(&element);
- continue;
- }
- std::unique_ptr<storage::BlobDataHandle> handle =
- blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid());
- std::unique_ptr<storage::BlobDataSnapshot> snapshot =
- handle->CreateSnapshot();
- if (snapshot->items().empty())
- continue;
- const auto& items = snapshot->items();
- for (const auto& item : items) {
- DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type());
- resolved_elements.push_back(item->data_element_ptr());
- }
- handles.push_back(std::move(handle));
- snapshots.push_back(std::move(snapshot));
- }
-
- const std::string uuid(base::GenerateGUID());
- uint64_t total_size = 0;
-
- storage::BlobDataBuilder blob_builder(uuid);
- for (size_t i = 0; i < resolved_elements.size(); ++i) {
- const ResourceRequestBodyImpl::Element& element = *resolved_elements[i];
- if (total_size != std::numeric_limits<uint64_t>::max() &&
- element.length() != std::numeric_limits<uint64_t>::max())
- total_size += element.length();
- else
- total_size = std::numeric_limits<uint64_t>::max();
- switch (element.type()) {
- case ResourceRequestBodyImpl::Element::TYPE_BYTES:
- blob_builder.AppendData(element.bytes(), element.length());
- break;
- case ResourceRequestBodyImpl::Element::TYPE_FILE:
- blob_builder.AppendFile(element.path(), element.offset(),
- element.length(),
- element.expected_modification_time());
- break;
- case ResourceRequestBodyImpl::Element::TYPE_BLOB:
- // Blob elements should be resolved beforehand.
- NOTREACHED();
- break;
- case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM:
- blob_builder.AppendFileSystemFile(element.filesystem_url(),
- element.offset(), element.length(),
- element.expected_modification_time());
- break;
- default:
- NOTIMPLEMENTED();
- }
+ blob_builder.AppendIPCDataElement(element);
}
request_body_blob_data_handle_ =
blob_storage_context_->AddFinishedBlob(&blob_builder);
- *blob_uuid = uuid;
- *blob_size = total_size;
+ *blob_uuid = blob_builder.uuid();
+ *blob_size = request_body_blob_data_handle_->size();
}
void ServiceWorkerURLRequestJob::DidPrepareFetchEvent(
@@ -584,12 +554,6 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
fetch_dispatcher_.reset();
ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status);
- // Check if we're not orphaned.
- if (!request()) {
- RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_REQUEST);
- return;
- }
-
ServiceWorkerMetrics::URLRequestJobResult result =
ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
if (!delegate_->RequestStillValid(&result)) {
@@ -776,8 +740,9 @@ bool ServiceWorkerURLRequestJob::IsFallbackToRendererNeeded() const {
fetch_type_ != ServiceWorkerFetchType::FOREIGN_FETCH &&
(request_mode_ == FETCH_REQUEST_MODE_CORS ||
request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) &&
- !request()->initiator().IsSameOriginWith(
- url::Origin(request()->url()));
+ (!request()->initiator().has_value() ||
+ !request()->initiator()->IsSameOriginWith(
+ url::Origin(request()->url())));
}
void ServiceWorkerURLRequestJob::SetResponseBodyType(ResponseBodyType type) {
@@ -858,8 +823,8 @@ bool ServiceWorkerURLRequestJob::HasRequestBody() {
return request_->has_upload() && body_.get() && blob_storage_context_;
}
-void ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted(bool success) {
- blob_construction_waiter_.reset();
+void ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved(bool success) {
+ file_size_resolver_.reset();
if (!success) {
RecordResult(
ServiceWorkerMetrics::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED);
@@ -893,6 +858,7 @@ void ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted(bool success) {
base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
weak_factory_.GetWeakPtr())));
worker_start_time_ = base::TimeTicks::Now();
+ fetch_dispatcher_->MaybeStartNavigationPreload(request());
fetch_dispatcher_->Run();
}
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 278f250a2ad..020842dd18f 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
@@ -33,12 +33,12 @@
namespace net {
class IOBuffer;
-}
+} // namespace net
namespace storage {
class BlobDataHandle;
class BlobStorageContext;
-}
+} // namespace storage
namespace content {
@@ -46,9 +46,7 @@ class ResourceContext;
class ResourceRequestBodyImpl;
class ServiceWorkerBlobReader;
class ServiceWorkerStreamReader;
-class ServiceWorkerContextCore;
class ServiceWorkerFetchDispatcher;
-class ServiceWorkerProviderHost;
class ServiceWorkerVersion;
class Stream;
@@ -143,7 +141,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
base::WeakPtr<ServiceWorkerURLRequestJob> GetWeakPtr();
private:
- class BlobConstructionWaiter;
+ class FileSizeResolver;
enum ResponseType {
NOT_DETERMINED,
@@ -169,7 +167,8 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
// Creates BlobDataHandle of the request body from |body_|. This handle
// |request_body_blob_data_handle_| will be deleted when
// ServiceWorkerURLRequestJob is deleted.
- // This must not be called until all blobs in |body_| finished construction.
+ // This must not be called until all files in |body_| with unknown size have
+ // their sizes populated.
void CreateRequestBodyBlob(std::string* blob_uuid, uint64_t* blob_size);
// For FORWARD_TO_SERVICE_WORKER case.
@@ -225,9 +224,9 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
bool IsMainResourceLoad() const;
- // For waiting for request body blobs to finish construction.
+ // For waiting for files sizes of request body files with unknown sizes.
bool HasRequestBody();
- void RequestBodyBlobsCompleted(bool success);
+ void RequestBodyFileSizesResolved(bool success);
// Not owned.
Delegate* delegate_;
@@ -279,7 +278,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
ServiceWorkerHeaderList cors_exposed_header_names_;
- std::unique_ptr<BlobConstructionWaiter> blob_construction_waiter_;
+ std::unique_ptr<FileSizeResolver> file_size_resolver_;
bool worker_already_activated_ = false;
EmbeddedWorkerStatus initial_worker_status_ = EmbeddedWorkerStatus::STOPPED;
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 bd63bb08fd2..88ed182f957 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
@@ -33,6 +33,8 @@
#include "content/browser/streams/stream_registry.h"
#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/common/request_context_frame_type.h"
#include "content/public/common/request_context_type.h"
@@ -58,8 +60,6 @@
namespace content {
-class ServiceWorkerURLRequestJobTest;
-
namespace {
const int kProviderID = 100;
@@ -178,6 +178,7 @@ class ServiceWorkerURLRequestJobTest
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);
}
@@ -336,7 +337,10 @@ class ServiceWorkerURLRequestJobTest
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
};
-TEST_F(ServiceWorkerURLRequestJobTest, Simple) {
+class ServiceWorkerURLRequestJobTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerURLRequestJobTest> {};
+
+TEST_P(ServiceWorkerURLRequestJobTestP, Simple) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
TestRequest(200, "OK", std::string(), true /* expect_valid_ssl */);
@@ -362,12 +366,13 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id, response_id,
+ embedded_worker_id, fetch_event_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -377,16 +382,14 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
std::string() /* response_cache_storage_cache_name */,
ServiceWorkerHeaderList() /* cors_exposed_header_names */),
base::Time::Now()));
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, event_finish_id,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback.Run(SERVICE_WORKER_OK, base::Time::Now());
}
private:
DISALLOW_COPY_AND_ASSIGN(ProviderDeleteHelper);
};
-TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostOnFetchEvent) {
+TEST_P(ServiceWorkerURLRequestJobTestP, DeletedProviderHostOnFetchEvent) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
// Shouldn't crash if the ProviderHost is deleted prior to completion of
// the fetch event.
@@ -409,7 +412,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostOnFetchEvent) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
-TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostBeforeFetchEvent) {
+TEST_P(ServiceWorkerURLRequestJobTestP, DeletedProviderHostBeforeFetchEvent) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
request_ = url_request_context_.CreateRequest(
GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
@@ -447,11 +450,12 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id, response_id,
+ embedded_worker_id, fetch_event_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -461,9 +465,7 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
std::string() /* response_cache_storage_cache_name */,
ServiceWorkerHeaderList() /* cors_exposed_header_names */),
base::Time::Now()));
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, event_finish_id,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback.Run(SERVICE_WORKER_OK, base::Time::Now());
}
std::string blob_uuid_;
@@ -473,7 +475,7 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
DISALLOW_COPY_AND_ASSIGN(BlobResponder);
};
-TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
+TEST_P(ServiceWorkerURLRequestJobTestP, BlobResponse) {
ChromeBlobStorageContext* blob_storage_context =
ChromeBlobStorageContext::GetFor(browser_context_.get());
std::string expected_response;
@@ -503,7 +505,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
-TEST_F(ServiceWorkerURLRequestJobTest, NonExistentBlobUUIDResponse) {
+TEST_P(ServiceWorkerURLRequestJobTestP, NonExistentBlobUUIDResponse) {
SetUpWithHelper(new BlobResponder("blob-id:nothing-is-here", 0));
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
TestRequest(500, "Service Worker Response Error", std::string(),
@@ -531,11 +533,12 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id, response_id,
+ embedded_worker_id, fetch_event_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -545,9 +548,7 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
std::string() /* response_cache_storage_cache_name */,
ServiceWorkerHeaderList() /* cors_exposed_header_names */),
base::Time::Now()));
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, event_finish_id,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback.Run(SERVICE_WORKER_OK, base::Time::Now());
}
const GURL stream_url_;
@@ -556,7 +557,7 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
DISALLOW_COPY_AND_ASSIGN(StreamResponder);
};
-TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
+TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
GetStreamContextForResourceContext(
@@ -605,7 +606,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
EXPECT_FALSE(HasWork());
}
-TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
+TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_DelayedRegistration) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
GetStreamContextForResourceContext(
@@ -655,8 +656,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
EXPECT_FALSE(HasWork());
}
-
-TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_QuickFinalize) {
+TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_QuickFinalize) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
GetStreamContextForResourceContext(
@@ -704,7 +704,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_QuickFinalize) {
EXPECT_FALSE(HasWork());
}
-TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Flush) {
+TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_Flush) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
GetStreamContextForResourceContext(
@@ -750,7 +750,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Flush) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
-TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
+TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponseAndCancel) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
GetStreamContextForResourceContext(
@@ -803,7 +803,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
-TEST_F(ServiceWorkerURLRequestJobTest,
+TEST_P(ServiceWorkerURLRequestJobTestP,
StreamResponse_DelayedRegistrationAndCancel) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
@@ -846,17 +846,19 @@ class FailFetchHelper : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
SimulateWorkerStopped(embedded_worker_id);
+ callback.Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now());
}
private:
DISALLOW_COPY_AND_ASSIGN(FailFetchHelper);
};
-TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
+TEST_P(ServiceWorkerURLRequestJobTestP, FailFetchDispatch) {
SetUpWithHelper(new FailFetchHelper);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -886,7 +888,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
}
// TODO(horo): Remove this test when crbug.com/485900 is fixed.
-TEST_F(ServiceWorkerURLRequestJobTest, MainScriptHTTPResponseInfoNotSet) {
+TEST_P(ServiceWorkerURLRequestJobTestP, MainScriptHTTPResponseInfoNotSet) {
// Shouldn't crash if MainScriptHttpResponseInfo is not set.
SetUpWithHelper(new EmbeddedWorkerTestHelper(base::FilePath()), false);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -913,7 +915,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, MainScriptHTTPResponseInfoNotSet) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
-TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
+TEST_P(ServiceWorkerURLRequestJobTestP, FailToActivate_MainResource) {
RunFailToActivateTest(RESOURCE_TYPE_MAIN_FRAME);
// The load should fail and we should have fallen back to network because
@@ -929,7 +931,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
EXPECT_EQ(host->controlling_version(), nullptr);
}
-TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
+TEST_P(ServiceWorkerURLRequestJobTestP, FailToActivate_Subresource) {
RunFailToActivateTest(RESOURCE_TYPE_IMAGE);
// The load should fail and we should not fall back to network because
@@ -952,20 +954,18 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
~EarlyResponseHelper() override {}
void FinishWaitUntil() {
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id_, event_finish_id_,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback_.Run(SERVICE_WORKER_OK, base::Time::Now());
}
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
- embedded_worker_id_ = embedded_worker_id;
- event_finish_id_ = event_finish_id;
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
+ callback_ = callback;
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id, response_id,
+ embedded_worker_id, fetch_event_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -978,14 +978,13 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
}
private:
- int embedded_worker_id_ = 0;
- int event_finish_id_ = 0;
+ FetchCallback callback_;
DISALLOW_COPY_AND_ASSIGN(EarlyResponseHelper);
};
// This simulates the case when a response is returned and the fetch event is
// still in flight.
-TEST_F(ServiceWorkerURLRequestJobTest, EarlyResponse) {
+TEST_P(ServiceWorkerURLRequestJobTestP, EarlyResponse) {
EarlyResponseHelper* helper = new EarlyResponseHelper;
SetUpWithHelper(helper);
@@ -1008,6 +1007,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, EarlyResponse) {
EXPECT_TRUE(version_->HasWork());
helper->FinishWaitUntil();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(version_->HasWork());
}
@@ -1019,7 +1019,7 @@ class DelayedResponseHelper : public EmbeddedWorkerTestHelper {
void Respond() {
SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
- embedded_worker_id_, response_id_,
+ embedded_worker_id_, fetch_event_id_,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
@@ -1029,30 +1029,29 @@ class DelayedResponseHelper : public EmbeddedWorkerTestHelper {
std::string() /* response_cache_storage_cache_name */,
ServiceWorkerHeaderList() /* cors_exposed_header_names */),
base::Time::Now()));
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id_, event_finish_id_,
- blink::WebServiceWorkerEventResultCompleted, base::Time::Now()));
+ callback_.Run(SERVICE_WORKER_OK, base::Time::Now());
}
protected:
void OnFetchEvent(int embedded_worker_id,
- int response_id,
- int event_finish_id,
- const ServiceWorkerFetchRequest& request) override {
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ const FetchCallback& callback) override {
embedded_worker_id_ = embedded_worker_id;
- response_id_ = response_id;
- event_finish_id_ = event_finish_id;
+ fetch_event_id_ = fetch_event_id;
+ callback_ = callback;
}
private:
int embedded_worker_id_ = 0;
- int response_id_ = 0;
- int event_finish_id_ = 0;
+ int fetch_event_id_ = 0;
+ FetchCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DelayedResponseHelper);
};
// Test cancelling the URLRequest while the fetch event is in flight.
-TEST_F(ServiceWorkerURLRequestJobTest, CancelRequest) {
+TEST_P(ServiceWorkerURLRequestJobTestP, CancelRequest) {
DelayedResponseHelper* helper = new DelayedResponseHelper;
SetUpWithHelper(helper);
@@ -1082,4 +1081,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, CancelRequest) {
// TODO(kinuko): Add more tests with different response data and also for
// FallbackToNetwork case.
+INSTANTIATE_TEST_CASE_P(ServiceWorkerURLRequestJobTest,
+ ServiceWorkerURLRequestJobTestP,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 337e6763752..60d70167be0 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -34,6 +34,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/common/origin_trials/trial_token_validator.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_messages.h"
@@ -345,6 +346,11 @@ ServiceWorkerVersion::~ServiceWorkerVersion() {
embedded_worker_->RemoveListener(this);
}
+void ServiceWorkerVersion::SetNavigationPreloadState(
+ const NavigationPreloadState& state) {
+ navigation_preload_state_ = state;
+}
+
void ServiceWorkerVersion::SetStatus(Status status) {
if (status_ == status)
return;
@@ -373,7 +379,8 @@ void ServiceWorkerVersion::SetStatus(Status status) {
// property.
// TODO(shimazu): Clarify the dependency of OnVersionStateChanged and
// |status_change_callbacks_|
- FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this));
+ for (auto& observer : listeners_)
+ observer.OnVersionStateChanged(this);
std::vector<base::Closure> callbacks;
callbacks.swap(status_change_callbacks_);
@@ -564,6 +571,24 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
return request_id;
}
+bool ServiceWorkerVersion::StartExternalRequest(
+ const std::string& request_uuid) {
+ // It's possible that the renderer is lying or the version started stopping
+ // right around the time of the IPC.
+ if (running_status() != EmbeddedWorkerStatus::RUNNING)
+ return false;
+
+ if (external_request_uuid_to_request_id_.count(request_uuid) > 0u)
+ return false;
+
+ int request_id =
+ StartRequest(ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST,
+ base::Bind(&ServiceWorkerVersion::CleanUpExternalRequest,
+ this, request_uuid));
+ external_request_uuid_to_request_id_[request_uuid] = request_id;
+ return true;
+}
+
bool ServiceWorkerVersion::FinishRequest(int request_id,
bool was_handled,
base::Time dispatch_event_time) {
@@ -583,12 +608,35 @@ bool ServiceWorkerVersion::FinishRequest(int request_id,
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
request, "Handled", was_handled);
pending_requests_.Remove(request_id);
- if (!HasWork())
- FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
+ if (!HasWork()) {
+ for (auto& observer : listeners_)
+ observer.OnNoWork(this);
+ }
return true;
}
+bool ServiceWorkerVersion::FinishExternalRequest(
+ const std::string& request_uuid) {
+ // It's possible that the renderer is lying or the version started stopping
+ // right around the time of the IPC.
+ if (running_status() != EmbeddedWorkerStatus::RUNNING)
+ return false;
+
+ RequestUUIDToRequestIDMap::iterator iter =
+ external_request_uuid_to_request_id_.find(request_uuid);
+ if (iter != external_request_uuid_to_request_id_.end()) {
+ int request_id = iter->second;
+ external_request_uuid_to_request_id_.erase(iter);
+ return FinishRequest(request_id, true, base::Time::Now());
+ }
+
+ // It is possible that the request was cancelled or timed out before and we
+ // won't find it in |external_request_uuid_to_request_id_|.
+ // Return true so we don't kill the process.
+ return true;
+}
+
void ServiceWorkerVersion::RunAfterStartWorker(
ServiceWorkerMetrics::EventType purpose,
const base::Closure& task,
@@ -631,8 +679,8 @@ void ServiceWorkerVersion::AddControllee(
controllee_map_[uuid] = provider_host;
// Keep the worker alive a bit longer right after a new controllee is added.
RestartTick(&idle_time_);
- FOR_EACH_OBSERVER(Listener, listeners_,
- OnControlleeAdded(this, provider_host));
+ for (auto& observer : listeners_)
+ observer.OnControlleeAdded(this, provider_host);
}
void ServiceWorkerVersion::RemoveControllee(
@@ -640,10 +688,12 @@ void ServiceWorkerVersion::RemoveControllee(
const std::string& uuid = provider_host->client_uuid();
DCHECK(base::ContainsKey(controllee_map_, uuid));
controllee_map_.erase(uuid);
- FOR_EACH_OBSERVER(Listener, listeners_,
- OnControlleeRemoved(this, provider_host));
- if (!HasControllee())
- FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
+ for (auto& observer : listeners_)
+ observer.OnControlleeRemoved(this, provider_host);
+ if (!HasControllee()) {
+ for (auto& observer : listeners_)
+ observer.OnNoControllees(this);
+ }
}
void ServiceWorkerVersion::AddStreamingURLRequestJob(
@@ -656,8 +706,10 @@ void ServiceWorkerVersion::AddStreamingURLRequestJob(
void ServiceWorkerVersion::RemoveStreamingURLRequestJob(
const ServiceWorkerURLRequestJob* request_job) {
streaming_url_request_jobs_.erase(request_job);
- if (!HasWork())
- FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
+ if (!HasWork()) {
+ for (auto& observer : listeners_)
+ observer.OnNoWork(this);
+ }
}
void ServiceWorkerVersion::AddListener(Listener* listener) {
@@ -700,6 +752,12 @@ void ServiceWorkerVersion::Doom() {
context_->storage()->PurgeResources(resources);
}
+void ServiceWorkerVersion::SetValidOriginTrialTokens(
+ const TrialTokenValidator::FeatureToTokensMap& tokens) {
+ origin_trial_tokens_ =
+ TrialTokenValidator::GetValidTokens(url::Origin(scope()), tokens);
+}
+
void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
embedded_worker()->set_devtools_attached(attached);
if (stop_when_devtools_detached_ && !attached) {
@@ -741,8 +799,20 @@ void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
const net::HttpResponseInfo& http_info) {
main_script_http_info_.reset(new net::HttpResponseInfo(http_info));
- FOR_EACH_OBSERVER(Listener, listeners_,
- OnMainScriptHttpResponseInfoSet(this));
+
+ // Updates |origin_trial_tokens_| if it is not set yet. This happens when:
+ // 1) The worker is a new one.
+ // OR
+ // 2) The worker is an existing one but the entry in ServiceWorkerDatabase
+ // was written by old version Chrome (< M56), so |origin_trial_tokens|
+ // wasn't set in the entry.
+ if (!origin_trial_tokens_) {
+ origin_trial_tokens_ = TrialTokenValidator::GetValidTokensFromHeaders(
+ url::Origin(scope()), http_info.headers.get());
+ }
+
+ for (auto& observer : listeners_)
+ observer.OnMainScriptHttpResponseInfoSet(this);
}
void ServiceWorkerVersion::SimulatePingTimeoutForTesting() {
@@ -811,7 +881,8 @@ void ServiceWorkerVersion::OnThreadStarted() {
}
void ServiceWorkerVersion::OnStarting() {
- FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
+ for (auto& observer : listeners_)
+ observer.OnRunningStateChanged(this);
}
void ServiceWorkerVersion::OnStarted() {
@@ -821,7 +892,8 @@ void ServiceWorkerVersion::OnStarted() {
// Fire all start callbacks.
scoped_refptr<ServiceWorkerVersion> protect(this);
FinishStartWorker(SERVICE_WORKER_OK);
- FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
+ for (auto& observer : listeners_)
+ observer.OnRunningStateChanged(this);
}
void ServiceWorkerVersion::OnStopping() {
@@ -837,7 +909,8 @@ void ServiceWorkerVersion::OnStopping() {
// when the worker starts up again.
SetTimeoutTimerInterval(
base::TimeDelta::FromSeconds(kStopWorkerTimeoutSeconds));
- FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
+ for (auto& observer : listeners_)
+ observer.OnRunningStateChanged(this);
}
void ServiceWorkerVersion::OnStopped(EmbeddedWorkerStatus old_status) {
@@ -870,7 +943,8 @@ void ServiceWorkerVersion::OnScriptLoadFailed() {
}
void ServiceWorkerVersion::OnRegisteredToDevToolsManager() {
- FOR_EACH_OBSERVER(Listener, listeners_, OnDevToolsRoutingIdChanged(this));
+ for (auto& observer : listeners_)
+ observer.OnDevToolsRoutingIdChanged(this);
}
void ServiceWorkerVersion::OnReportException(
@@ -878,11 +952,10 @@ void ServiceWorkerVersion::OnReportException(
int line_number,
int column_number,
const GURL& source_url) {
- FOR_EACH_OBSERVER(
- Listener,
- listeners_,
- OnErrorReported(
- this, error_message, line_number, column_number, source_url));
+ for (auto& observer : listeners_) {
+ observer.OnErrorReported(this, error_message, line_number, column_number,
+ source_url);
+ }
}
void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
@@ -890,14 +963,10 @@ void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
const base::string16& message,
int line_number,
const GURL& source_url) {
- FOR_EACH_OBSERVER(Listener,
- listeners_,
- OnReportConsoleMessage(this,
- source_identifier,
- message_level,
- message,
- line_number,
- source_url));
+ for (auto& observer : listeners_) {
+ observer.OnReportConsoleMessage(this, source_identifier, message_level,
+ message, line_number, source_url);
+ }
}
bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
@@ -1094,7 +1163,8 @@ void ServiceWorkerVersion::OnSetCachedMetadataFinished(int64_t callback_id,
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerVersion::OnSetCachedMetadata",
callback_id, "result", result);
- FOR_EACH_OBSERVER(Listener, listeners_, OnCachedMetadataUpdated(this));
+ for (auto& observer : listeners_)
+ observer.OnCachedMetadataUpdated(this);
}
void ServiceWorkerVersion::OnClearCachedMetadata(const GURL& url) {
@@ -1112,7 +1182,8 @@ void ServiceWorkerVersion::OnClearCachedMetadataFinished(int64_t callback_id,
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerVersion::OnClearCachedMetadata",
callback_id, "result", result);
- FOR_EACH_OBSERVER(Listener, listeners_, OnCachedMetadataUpdated(this));
+ for (auto& observer : listeners_)
+ observer.OnCachedMetadataUpdated(this);
}
void ServiceWorkerVersion::OnPostMessageToClient(
@@ -1765,6 +1836,7 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
iter.Advance();
}
pending_requests_.Clear();
+ external_request_uuid_to_request_id_.clear();
// Close all mojo services. This will also fire and clear all callbacks
// for messages that are still outstanding for those services.
@@ -1773,11 +1845,14 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
// TODO(falken): Call SWURLRequestJob::ClearStream here?
streaming_url_request_jobs_.clear();
- FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
- if (should_restart)
+ for (auto& observer : listeners_)
+ observer.OnRunningStateChanged(this);
+ if (should_restart) {
StartWorkerInternal();
- else if (!HasWork())
- FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
+ } else if (!HasWork()) {
+ for (auto& observer : listeners_)
+ observer.OnNoWork(this);
+ }
}
void ServiceWorkerVersion::OnMojoConnectionError(const char* service_name) {
@@ -1801,4 +1876,12 @@ void ServiceWorkerVersion::FinishStartWorker(ServiceWorkerStatusCode status) {
RunCallbacks(this, &start_callbacks_, status);
}
+void ServiceWorkerVersion::CleanUpExternalRequest(
+ const std::string& request_uuid,
+ ServiceWorkerStatusCode status) {
+ if (status == SERVICE_WORKER_OK)
+ return;
+ external_request_uuid_to_request_id_.erase(request_uuid);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 5026700bcbe..8e08831ea13 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -33,11 +33,12 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_script_cache_map.h"
#include "content/common/content_export.h"
+#include "content/common/origin_trials/trial_token_validator.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -53,7 +54,6 @@ class HttpResponseInfo;
namespace content {
-class EmbeddedWorkerRegistry;
class ServiceWorkerContextCore;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
@@ -169,6 +169,17 @@ class CONTENT_EXPORT ServiceWorkerVersion
foreign_fetch_origins_ = origins;
}
+ // Meaningful only if this version is active.
+ const NavigationPreloadState& navigation_preload_state() const {
+ DCHECK(status_ == ACTIVATING || status_ == ACTIVATED) << status_;
+ return navigation_preload_state_;
+ }
+ // Only intended for use by ServiceWorkerRegistration. Generally use
+ // ServiceWorkerRegistration::EnableNavigationPreload or
+ // ServiceWorkerRegistration::SetNavigationPreloadHeader instead of this
+ // function.
+ void SetNavigationPreloadState(const NavigationPreloadState& state);
+
ServiceWorkerMetrics::Site site_for_uma() const { return site_for_uma_; }
// This sets the new status and also run status change callbacks
@@ -235,6 +246,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
const base::TimeDelta& timeout,
TimeoutBehavior timeout_behavior);
+ // Starts a request of type EventType::EXTERNAL_REQUEST.
+ // Provides a mechanism to external clients to keep the worker running.
+ // |request_uuid| is a GUID for clients to identify the request.
+ // Returns true if the request was successfully scheduled to starrt.
+ bool StartExternalRequest(const std::string& request_uuid);
+
// Informs ServiceWorkerVersion that an event has finished being dispatched.
// Returns false if no pending requests with the provided id exist, for
// example if the request has already timed out.
@@ -245,6 +262,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
bool was_handled,
base::Time dispatch_event_time);
+ // Finishes an external request that was started by StartExternalRequest().
+ // Returns false if there was an error finishing the request: e.g. the request
+ // was not found or the worker already terminated.
+ bool FinishExternalRequest(const std::string& request_uuid);
+
// Connects to a specific mojo service exposed by the (running) service
// worker. If a connection to a service for the same Interface already exists
// this will return that existing connection. The |request_id| must be a value
@@ -353,6 +375,19 @@ class CONTENT_EXPORT ServiceWorkerVersion
pause_after_download_ = pause_after_download;
}
+ // Returns nullptr if the main script is not loaded yet and:
+ // 1) The worker is a new one.
+ // OR
+ // 2) The worker is an existing one but the entry in ServiceWorkerDatabase
+ // was written by old version of Chrome (< M56), so |origin_trial_tokens|
+ // wasn't set in the entry.
+ const TrialTokenValidator::FeatureToTokensMap* origin_trial_tokens() const {
+ return origin_trial_tokens_.get();
+ }
+ // Set valid tokens in |tokens|. Invalid tokens in |tokens| are ignored.
+ void SetValidOriginTrialTokens(
+ const TrialTokenValidator::FeatureToTokensMap& tokens);
+
void SetDevToolsAttached(bool attached);
// Sets the HttpResponseInfo used to load the main script.
@@ -369,6 +404,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// requests, in-progress streaming URLRequestJobs, or pending start callbacks.
bool HasWork() const;
+ // Returns the number of pending external request count of this worker.
+ size_t GetExternalRequestCountForTest() const {
+ return external_request_uuid_to_request_id_.size();
+ }
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class ServiceWorkerMetrics;
@@ -376,22 +416,23 @@ class CONTENT_EXPORT ServiceWorkerVersion
friend class ServiceWorkerStallInStoppingTest;
friend class ServiceWorkerURLRequestJobTest;
friend class ServiceWorkerVersionBrowserTest;
- friend class ServiceWorkerVersionTest;
+ friend class ServiceWorkerVersionTestP;
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP,
ActivateWaitingVersion);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP,
FallbackWithNoFetchHandler);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, IdleTimeout);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, SetDevToolsAttached);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_FreshWorker);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, IdleTimeout);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, SetDevToolsAttached);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, StaleUpdate_FreshWorker);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
StaleUpdate_NonActiveWorker);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_StartWorker);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_RunningWorker);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, StaleUpdate_StartWorker);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
+ StaleUpdate_RunningWorker);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
StaleUpdate_DoNotDeferTimer);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestTimeout);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestTimeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerFailToStartTest, Timeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
TimeoutStartingWorker);
@@ -399,12 +440,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
TimeoutWorkerInEvent);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenStart);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenRestart);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
RegisterForeignFetchScopes);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestCustomizedTimeout);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestCustomizedTimeout);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
RequestCustomizedTimeoutKill);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, MixedRequestTimeouts);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, MixedRequestTimeouts);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, EarlyResponse);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, CancelRequest);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerActivationTest, SkipWaiting);
@@ -681,6 +722,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// callbacks.
void FinishStartWorker(ServiceWorkerStatusCode status);
+ // Removes any pending external request that has GUID of |request_uuid|.
+ void CleanUpExternalRequest(const std::string& request_uuid,
+ ServiceWorkerStatusCode status);
+
const int64_t version_id_;
const int64_t registration_id_;
const GURL script_url_;
@@ -688,6 +733,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::vector<GURL> foreign_fetch_scopes_;
std::vector<url::Origin> foreign_fetch_origins_;
FetchHandlerExistence fetch_handler_existence_;
+ // The source of truth for navigation preload state is the
+ // ServiceWorkerRegistration. |navigation_preload_state_| is essentially a
+ // cached value because it must be looked up quickly and a live registration
+ // doesn't necessarily exist whenever there is a live version.
+ NavigationPreloadState navigation_preload_state_;
ServiceWorkerMetrics::Site site_for_uma_;
Status status_ = NEW;
@@ -700,6 +750,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// fetch, sync, etc. events.
IDMap<PendingRequest, IDMapOwnPointer> pending_requests_;
+ // Container for pending external requests for this service worker.
+ // (key, value): (request uuid, request id).
+ using RequestUUIDToRequestIDMap = std::map<std::string, int>;
+ RequestUUIDToRequestIDMap external_request_uuid_to_request_id_;
+
// Stores all open connections to mojo services. Maps the service name to
// the actual interface pointer. When a connection is closed it is removed
// from this map.
@@ -748,6 +803,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::vector<int> pending_skip_waiting_requests_;
std::unique_ptr<net::HttpResponseInfo> main_script_http_info_;
+ std::unique_ptr<TrialTokenValidator::FeatureToTokensMap> origin_trial_tokens_;
+
// If not OK, the reason that StartWorker failed. Used for
// running |start_callbacks_|.
ServiceWorkerStatusCode start_worker_status_ = SERVICE_WORKER_OK;
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 3fe064a7f08..33f78fee892 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -24,7 +24,7 @@
#include "content/public/test/test_service.mojom.h"
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
#include "testing/gtest/include/gtest/gtest.h"
// IPC messages for testing ---------------------------------------------------
@@ -291,10 +291,13 @@ class ServiceWorkerVersionTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
};
+class ServiceWorkerVersionTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerVersionTest> {};
+
class MessageReceiverDisallowStart : public MessageReceiver {
public:
- MessageReceiverDisallowStart()
- : MessageReceiver() {}
+ MessageReceiverDisallowStart(bool is_mojo_enabled)
+ : MessageReceiver(), is_mojo_enabled_(is_mojo_enabled) {}
~MessageReceiverDisallowStart() override {}
enum class StartMode { STALL, FAIL, SUCCEED };
@@ -308,7 +311,14 @@ class MessageReceiverDisallowStart : public MessageReceiver {
case StartMode::STALL:
break; // Do nothing.
case StartMode::FAIL:
- OnStopWorker(embedded_worker_id);
+ if (is_mojo_enabled_) {
+ ASSERT_EQ(current_mock_instance_index_ + 1,
+ mock_instance_clients()->size());
+ // Remove the connection by peer
+ mock_instance_clients()->at(current_mock_instance_index_).reset();
+ } else {
+ OnStopWorker(embedded_worker_id);
+ }
break;
case StartMode::SUCCEED:
MessageReceiver::OnStartWorker(embedded_worker_id,
@@ -316,19 +326,21 @@ class MessageReceiverDisallowStart : public MessageReceiver {
script_url, pause_after_download);
break;
}
+ current_mock_instance_index_++;
}
void set_start_mode(StartMode mode) { mode_ = mode; }
private:
+ const bool is_mojo_enabled_;
+ uint32_t current_mock_instance_index_ = 0;
StartMode mode_ = StartMode::STALL;
DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
};
-class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
+class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTestP {
protected:
- ServiceWorkerFailToStartTest()
- : ServiceWorkerVersionTest() {}
+ ServiceWorkerFailToStartTest() : ServiceWorkerVersionTestP() {}
void set_start_mode(MessageReceiverDisallowStart::StartMode mode) {
MessageReceiverDisallowStart* helper =
@@ -337,16 +349,43 @@ class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
}
std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
- return base::MakeUnique<MessageReceiverDisallowStart>();
+ return base::MakeUnique<MessageReceiverDisallowStart>(is_mojo_enabled());
}
private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest);
};
+class NoOpStopWorkerEmbeddedWorkerInstanceClient
+ : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient {
+ public:
+ explicit NoOpStopWorkerEmbeddedWorkerInstanceClient(
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+ : EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
+ ~NoOpStopWorkerEmbeddedWorkerInstanceClient() override {
+ // Stop callback should be called once.
+ if (pending_stop_callback_)
+ pending_stop_callback_.Run();
+ }
+
+ protected:
+ void StopWorker(const StopWorkerCallback& callback) override {
+ pending_stop_callback_ = std::move(callback);
+ // Do nothing.
+ }
+
+ StopWorkerCallback pending_stop_callback_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NoOpStopWorkerEmbeddedWorkerInstanceClient);
+};
+
class MessageReceiverDisallowStop : public MessageReceiver {
public:
- MessageReceiverDisallowStop() : MessageReceiver() {}
+ MessageReceiverDisallowStop() : MessageReceiver() {
+ CreateAndRegisterMockInstanceClient<
+ NoOpStopWorkerEmbeddedWorkerInstanceClient>(AsWeakPtr());
+ }
~MessageReceiverDisallowStop() override {}
void OnStopWorker(int embedded_worker_id) override {
@@ -357,9 +396,9 @@ class MessageReceiverDisallowStop : public MessageReceiver {
DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStop);
};
-class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTest {
+class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTestP {
protected:
- ServiceWorkerStallInStoppingTest() : ServiceWorkerVersionTest() {}
+ ServiceWorkerStallInStoppingTest() : ServiceWorkerVersionTestP() {}
std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
return base::MakeUnique<MessageReceiverDisallowStop>();
@@ -374,7 +413,8 @@ class MessageReceiverMojoTestService : public MessageReceiver {
MessageReceiverMojoTestService() : MessageReceiver() {}
~MessageReceiverMojoTestService() override {}
- void OnSetupMojo(shell::InterfaceRegistry* registry) override {
+ void OnSetupMojo(int thread_id,
+ service_manager::InterfaceRegistry* registry) override {
registry->AddInterface(base::Bind(&TestServiceImpl::Create));
}
@@ -382,9 +422,9 @@ class MessageReceiverMojoTestService : public MessageReceiver {
DISALLOW_COPY_AND_ASSIGN(MessageReceiverMojoTestService);
};
-class ServiceWorkerVersionWithMojoTest : public ServiceWorkerVersionTest {
+class ServiceWorkerVersionWithMojoTest : public ServiceWorkerVersionTestP {
protected:
- ServiceWorkerVersionWithMojoTest() : ServiceWorkerVersionTest() {}
+ ServiceWorkerVersionWithMojoTest() : ServiceWorkerVersionTestP() {}
std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
return base::MakeUnique<MessageReceiverMojoTestService>();
@@ -394,7 +434,7 @@ class ServiceWorkerVersionWithMojoTest : public ServiceWorkerVersionTest {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionWithMojoTest);
};
-TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
+TEST_P(ServiceWorkerVersionTestP, ConcurrentStartAndStop) {
// Call StartWorker() multiple times.
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
@@ -462,7 +502,7 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
EXPECT_EQ(SERVICE_WORKER_OK, status3);
}
-TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
+TEST_P(ServiceWorkerVersionTestP, DispatchEventToStoppedWorker) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Dispatch an event without starting the worker.
@@ -482,7 +522,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
+TEST_P(ServiceWorkerVersionTestP, StartUnregisteredButStillLiveWorker) {
// Start the worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -516,7 +556,7 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
+TEST_P(ServiceWorkerVersionTestP, ReceiveMessageFromWorker) {
// Start worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -540,7 +580,7 @@ TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
EXPECT_EQ(777, receiver.received_values()[1]);
}
-TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
+TEST_P(ServiceWorkerVersionTestP, InstallAndWaitCompletion) {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
// Wait for the completion.
@@ -556,7 +596,7 @@ TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
}
-TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
+TEST_P(ServiceWorkerVersionTestP, ActivateAndWaitCompletion) {
// TODO(mek): This test (and the one above for the install event) made more
// sense back when ServiceWorkerVersion was responsible for updating the
// status. Now a better version of this test should probably be added to
@@ -577,7 +617,7 @@ TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
-TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
+TEST_P(ServiceWorkerVersionTestP, RepeatedlyObserveStatusChanges) {
EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
// Repeatedly observe status changes (the callback re-registers itself).
@@ -600,7 +640,7 @@ TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
}
-TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
+TEST_P(ServiceWorkerVersionTestP, IdleTimeout) {
// Used to reliably test when the idle time gets reset regardless of clock
// granularity.
const base::TimeDelta kOneSecond = base::TimeDelta::FromSeconds(1);
@@ -665,7 +705,7 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
EXPECT_LT(idle_time, version_->idle_time_);
}
-TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
+TEST_P(ServiceWorkerVersionTestP, SetDevToolsAttached) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
@@ -695,7 +735,7 @@ TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
+TEST_P(ServiceWorkerVersionTestP, StoppingBeforeDestruct) {
RunningStateListener listener;
version_->AddListener(&listener);
@@ -712,7 +752,7 @@ TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
}
// Test that update isn't triggered for a non-stale worker.
-TEST_F(ServiceWorkerVersionTest, StaleUpdate_FreshWorker) {
+TEST_P(ServiceWorkerVersionTestP, StaleUpdate_FreshWorker) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
registration_->set_last_update_check(base::Time::Now());
@@ -723,7 +763,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_FreshWorker) {
}
// Test that update isn't triggered for a non-active worker.
-TEST_F(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker) {
+TEST_P(ServiceWorkerVersionTestP, StaleUpdate_NonActiveWorker) {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
registration_->SetInstallingVersion(version_);
registration_->set_last_update_check(GetYesterday());
@@ -734,7 +774,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker) {
}
// Test that staleness is detected when starting a worker.
-TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
+TEST_P(ServiceWorkerVersionTestP, StaleUpdate_StartWorker) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
// Starting the worker marks it as stale.
@@ -754,7 +794,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
}
// Test that staleness is detected on a running worker.
-TEST_F(ServiceWorkerVersionTest, StaleUpdate_RunningWorker) {
+TEST_P(ServiceWorkerVersionTestP, StaleUpdate_RunningWorker) {
// Start a fresh worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
@@ -780,7 +820,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_RunningWorker) {
}
// Test that a stream of events doesn't restart the timer.
-TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
+TEST_P(ServiceWorkerVersionTestP, StaleUpdate_DoNotDeferTimer) {
// Make a stale worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
@@ -816,7 +856,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
}
-TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
+TEST_P(ServiceWorkerVersionTestP, RequestTimeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -845,7 +885,7 @@ TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
+TEST_P(ServiceWorkerVersionTestP, RequestCustomizedTimeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -872,7 +912,7 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
+TEST_P(ServiceWorkerVersionTestP, RequestCustomizedTimeoutKill) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -899,7 +939,7 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
+TEST_P(ServiceWorkerVersionTestP, MixedRequestTimeouts) {
ServiceWorkerStatusCode sync_status =
SERVICE_WORKER_ERROR_NETWORK; // dummy value
ServiceWorkerStatusCode fetch_status =
@@ -950,7 +990,7 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
-TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
+TEST_P(ServiceWorkerFailToStartTest, RendererCrash) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
@@ -973,7 +1013,7 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
-TEST_F(ServiceWorkerFailToStartTest, Timeout) {
+TEST_P(ServiceWorkerFailToStartTest, Timeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
// Start starting the worker.
@@ -999,7 +1039,7 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
// Test that a service worker stalled in stopping will timeout and not get in a
// sticky error state.
-TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
+TEST_P(ServiceWorkerStallInStoppingTest, DetachThenStart) {
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -1047,7 +1087,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
// Test that a service worker stalled in stopping with a start worker
// request queued up will timeout and restart.
-TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
+TEST_P(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -1079,7 +1119,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
+TEST_P(ServiceWorkerVersionTestP, RegisterForeignFetchScopes) {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -1155,7 +1195,7 @@ TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
EXPECT_EQ(valid_origin, version_->foreign_fetch_origins_[0]);
}
-TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
+TEST_P(ServiceWorkerVersionTestP, RendererCrashDuringEvent) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1190,7 +1230,7 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
+TEST_P(ServiceWorkerVersionWithMojoTest, MojoService) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1216,7 +1256,7 @@ TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
+TEST_P(ServiceWorkerVersionTestP, NonExistentMojoService) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1242,7 +1282,7 @@ TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
+TEST_P(ServiceWorkerVersionTestP, DispatchEvent) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
// Activate and start worker.
@@ -1288,7 +1328,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
+TEST_P(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
helper_->SimulateAddProcessToPattern(pattern_,
@@ -1347,7 +1387,7 @@ TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
base::RunLoop().RunUntilIdle();
}
-TEST_F(ServiceWorkerFailToStartTest, RestartStalledWorker) {
+TEST_P(ServiceWorkerFailToStartTest, RestartStalledWorker) {
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
@@ -1370,7 +1410,7 @@ TEST_F(ServiceWorkerFailToStartTest, RestartStalledWorker) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
-TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
+TEST_P(ServiceWorkerVersionTestP, DispatchConcurrentEvent) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
// Activate and start worker.
@@ -1449,7 +1489,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
+TEST_P(ServiceWorkerVersionTestP, DispatchSimpleEvent_Completed) {
ServiceWorkerStatusCode status =
SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
@@ -1486,7 +1526,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
EXPECT_EQ(SERVICE_WORKER_OK, status);
}
-TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
+TEST_P(ServiceWorkerVersionTestP, DispatchSimpleEvent_Rejected) {
ServiceWorkerStatusCode status =
SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
@@ -1523,7 +1563,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
}
-TEST_F(ServiceWorkerVersionTest, DispatchEvent_MultipleResponse) {
+TEST_P(ServiceWorkerVersionTestP, DispatchEvent_MultipleResponse) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
// Activate and start worker.
@@ -1592,9 +1632,9 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent_MultipleResponse) {
base::Time::Now()));
}
-class ServiceWorkerNavigationHintUMATest : public ServiceWorkerVersionTest {
+class ServiceWorkerNavigationHintUMATest : public ServiceWorkerVersionTestP {
protected:
- ServiceWorkerNavigationHintUMATest() : ServiceWorkerVersionTest() {}
+ ServiceWorkerNavigationHintUMATest() : ServiceWorkerVersionTestP() {}
void StartWorker(ServiceWorkerMetrics::EventType purpose) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -1675,25 +1715,25 @@ const char ServiceWorkerNavigationHintUMATest::kLinkTapUnconfirmed[] =
const char ServiceWorkerNavigationHintUMATest::kLinkTapDown[] =
"ServiceWorker.NavigationHintPrecision.LINK_TAP_DOWN";
-TEST_F(ServiceWorkerNavigationHintUMATest, LinkMouseDown) {
+TEST_P(ServiceWorkerNavigationHintUMATest, LinkMouseDown) {
SimpleNavigationHintTest(
ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_MOUSE_DOWN,
kLinkMouseDown, {kLinkTapUnconfirmed, kLinkTapDown});
}
-TEST_F(ServiceWorkerNavigationHintUMATest, LinkTapUnconfirmed) {
+TEST_P(ServiceWorkerNavigationHintUMATest, LinkTapUnconfirmed) {
SimpleNavigationHintTest(
ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_TAP_UNCONFIRMED,
kLinkTapUnconfirmed, {kLinkMouseDown, kLinkTapDown});
}
-TEST_F(ServiceWorkerNavigationHintUMATest, LinkTapDown) {
+TEST_P(ServiceWorkerNavigationHintUMATest, LinkTapDown) {
SimpleNavigationHintTest(
ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_TAP_DOWN,
kLinkTapDown, {kLinkMouseDown, kLinkTapUnconfirmed});
}
-TEST_F(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
+TEST_P(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -1727,7 +1767,7 @@ TEST_F(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
histogram_tester_.ExpectBucketCount(kNavigationHintPrecision, false, 0);
}
-TEST_F(ServiceWorkerNavigationHintUMATest, StartWhileStopping) {
+TEST_P(ServiceWorkerNavigationHintUMATest, StartWhileStopping) {
StartWorker(ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_MOUSE_DOWN);
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
version_->StopWorker(CreateReceiverOnCurrentThread(&status));
@@ -1745,4 +1785,20 @@ TEST_F(ServiceWorkerNavigationHintUMATest, StartWhileStopping) {
histogram_tester_.ExpectTotalCount(kLinkTapDown, 1);
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerVersionTestP,
+ ServiceWorkerVersionTestP,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerFailToStartTest,
+ ServiceWorkerFailToStartTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerNavigationHintUMATest,
+ ServiceWorkerNavigationHintUMATest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerStallInStoppingTest,
+ ServiceWorkerStallInStoppingTest,
+ testing::Bool());
+INSTANTIATE_TEST_CASE_P(ServiceWorkerVersionWithMojoTest,
+ ServiceWorkerVersionWithMojoTest,
+ testing::Bool());
+
} // namespace content
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 bf226ad74f8..0ffd4ecac31 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
@@ -71,6 +71,7 @@ ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
}
ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
+ Kill();
DCHECK_EQ(did_notify_started_, did_notify_finished_);
}
@@ -285,7 +286,10 @@ void ServiceWorkerWriteToCacheJob::OnResponseStarted(net::URLRequest* request,
}
}
- if (version_->script_url() == url_) {
+ if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
+ // TODO(nhiroki): Temporary check for debugging (https://crbug.com/485900).
+ CHECK_EQ(version_->script_url(), url_);
+
std::string mime_type;
request->GetMimeType(&mime_type);
if (mime_type != "application/x-javascript" &&
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 4f9e158dad3..011559e365f 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
@@ -26,7 +26,6 @@ namespace content {
class ServiceWorkerCacheWriter;
class ServiceWorkerContextCore;
-class ServiceWorkerVersions;
// A URLRequestJob derivative used to cache the main script
// and its imports during the initial install of a new version.
@@ -61,13 +60,13 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
const static net::Error kIdenticalScriptError;
private:
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateBefore24Hours);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateAfter24Hours);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
UpdateForceBypassCache);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
ServiceWorkerDataRequestAnnotation);
~ServiceWorkerWriteToCacheJob() override;
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 509dd9bd73e..0365891ab5d 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
@@ -439,7 +439,10 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
int64_t next_version_id_ = 1L;
};
-TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
+class ServiceWorkerWriteToCacheJobTestP
+ : public MojoServiceWorkerTestP<ServiceWorkerWriteToCacheJobTest> {};
+
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Normal) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateNormalURLRequestJob));
request_->Start();
@@ -449,7 +452,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
version_->script_cache_map()->LookupResourceId(script_url_));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, InvalidMimeType) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateInvalidMimeTypeJob));
request_->Start();
@@ -460,7 +463,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
version_->script_cache_map()->LookupResourceId(script_url_));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, SSLCertificateError) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateSSLCertificateErrorJob));
request_->Start();
@@ -471,7 +474,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
version_->script_cache_map()->LookupResourceId(script_url_));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, CertStatusError) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateCertStatusErrorJob));
request_->Start();
@@ -482,14 +485,14 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
version_->script_cache_map()->LookupResourceId(script_url_));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_SameScript) {
std::string response = GenerateLongResponse();
CreateIncumbent(response);
scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_SameSizeScript) {
std::string response = GenerateLongResponse();
CreateIncumbent(response);
@@ -524,7 +527,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
registration_->SetWaitingVersion(version);
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_TruncatedScript) {
std::string response = GenerateLongResponse();
CreateIncumbent(response);
@@ -553,7 +556,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
registration_->SetWaitingVersion(version);
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_ElongatedScript) {
std::string original_response = GenerateLongResponse();
CreateIncumbent(original_response);
@@ -576,7 +579,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
registration_->SetWaitingVersion(version);
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_EmptyScript) {
// Create empty incumbent.
CreateIncumbent(std::string());
@@ -596,7 +599,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, Error) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateFailedURLRequestJob));
request_->Start();
@@ -607,7 +610,7 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
version_->script_cache_map()->LookupResourceId(script_url_));
}
-TEST_F(ServiceWorkerWriteToCacheJobTest, FailedWriteHeadersToCache) {
+TEST_P(ServiceWorkerWriteToCacheJobTestP, FailedWriteHeadersToCache) {
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateNormalURLRequestJob));
DisableCache();
@@ -617,4 +620,8 @@ TEST_F(ServiceWorkerWriteToCacheJobTest, FailedWriteHeadersToCache) {
EXPECT_EQ(net::ERR_FAILED, request_->status().error());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerWriteToCacheJobTest,
+ ServiceWorkerWriteToCacheJobTestP,
+ testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index 4f801271466..7bed3fd8cc0 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -55,11 +55,11 @@ class SessionHistoryTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleEchoTitleRequest, "/echotitle"));
+ ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
}
@@ -333,9 +333,6 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) {
// navigations. Bug 730379.
// If this flakes use http://crbug.com/61619.
IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FragmentBackForward) {
- embedded_test_server()->RegisterRequestHandler(
- base::Bind(&HandleEchoTitleRequest, "/echotitle"));
-
ASSERT_FALSE(CanGoBack());
GURL fragment(GetURL("fragment.html"));
diff --git a/chromium/content/browser/shapedetection/shapedetection_browsertest.cc b/chromium/content/browser/shapedetection/shapedetection_browsertest.cc
new file mode 100644
index 00000000000..fa24aa4745c
--- /dev/null
+++ b/chromium/content/browser/shapedetection/shapedetection_browsertest.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/strings/string_tokenizer.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"
+
+namespace content {
+
+// TODO(xianglu): Enable other platforms with support. https://crbug.com/646083
+#if defined(OS_ANDROID)
+#define MAYBE_ShapeDetectionBrowserTest ShapeDetectionBrowserTest
+#else
+#define MAYBE_ShapeDetectionBrowserTest DISABLED_ShapeDetectionBrowserTest
+#endif
+
+namespace {
+
+const char kFaceDetectionTestHtml[] = "/media/face_detection_test.html";
+
+} // namespace
+
+// This class contains content_browsertests for Shape Detection API, which
+// allows for generating bounding boxes for faces on still images..
+class MAYBE_ShapeDetectionBrowserTest : public ContentBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Specific flag to enable ShapeDetection and DOMRect API.
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kEnableBlinkFeatures, "ShapeDetection, GeometryInterfaces");
+ }
+
+ protected:
+ void RunDetectFacesOnImageUrl(
+ const std::string& image_path,
+ const std::vector<std::vector<float>>& expected_results) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ const GURL html_url(embedded_test_server()->GetURL(kFaceDetectionTestHtml));
+ const GURL image_url(embedded_test_server()->GetURL(image_path));
+ NavigateToURL(shell(), html_url);
+ const std::string js_command =
+ "detectFacesOnImageUrl('" + image_url.spec() + "')";
+ std::string response_string;
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractString(shell(), js_command, &response_string));
+
+ base::StringTokenizer outer_tokenizer(response_string, "#");
+ std::vector<std::vector<float>> results;
+ while (outer_tokenizer.GetNext()) {
+ std::string s = outer_tokenizer.token().c_str();
+ std::vector<float> res;
+ base::StringTokenizer inner_tokenizer(s, ",");
+ while (inner_tokenizer.GetNext())
+ res.push_back(atof(inner_tokenizer.token().c_str()));
+ results.push_back(res);
+ }
+
+ ASSERT_EQ(expected_results.size(), results.size()) << "Number of faces";
+ for (size_t face_id = 0; face_id < results.size(); ++face_id) {
+ const std::vector<float> expected_result = expected_results[face_id];
+ const std::vector<float> result = results[face_id];
+ for (size_t i = 0; i < 4; ++i)
+ EXPECT_NEAR(expected_result[i], result[i], 0.1) << "At index " << i;
+ }
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(MAYBE_ShapeDetectionBrowserTest,
+ DetectFacesOnImageWithNoFaces) {
+ const std::string image_path = "/blank.jpg";
+ const std::vector<std::vector<float>> expected_empty_results;
+ RunDetectFacesOnImageUrl(image_path, expected_empty_results);
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_ShapeDetectionBrowserTest,
+ DetectFacesOnImageWithOneFace) {
+ const std::string image_path = "/single_face.jpg";
+ const std::vector<float> expected_result = {68.640625, 102.96875, 171.5625,
+ 171.5625};
+ const std::vector<std::vector<float>> expected_results = {expected_result};
+ RunDetectFacesOnImageUrl(image_path, expected_results);
+}
+
+} // namespace content
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 e635448ea27..291df2c4872 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -474,9 +474,8 @@ void SharedWorkerServiceImpl::RenderFrameDetached(int render_process_id,
void SharedWorkerServiceImpl::NotifyWorkerDestroyed(int worker_process_id,
int worker_route_id) {
- FOR_EACH_OBSERVER(WorkerServiceObserver,
- observers_,
- WorkerDestroyed(worker_process_id, worker_route_id));
+ for (auto& observer : observers_)
+ observer.WorkerDestroyed(worker_process_id, worker_route_id);
}
blink::WebWorkerCreationError
@@ -593,10 +592,8 @@ void SharedWorkerServiceImpl::RenderProcessReservedCallback(
host->Start(pause_on_start);
ProcessRouteIdPair key(worker_process_id, worker_route_id);
worker_hosts_[key] = std::move(host);
- FOR_EACH_OBSERVER(
- WorkerServiceObserver,
- observers_,
- WorkerCreated(url, name, worker_process_id, worker_route_id));
+ for (auto& observer : observers_)
+ observer.WorkerCreated(url, name, worker_process_id, worker_route_id);
}
void SharedWorkerServiceImpl::RenderProcessReserveFailedCallback(
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index a55d786e8db..7980783a7d3 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -239,13 +239,19 @@ bool SiteInstanceImpl::RequiresDedicatedProcess() {
return DoesSiteRequireDedicatedProcess(GetBrowserContext(), site_);
}
+bool SiteInstanceImpl::IsDefaultSubframeSiteInstance() const {
+ return is_default_subframe_site_instance_;
+}
+
void SiteInstanceImpl::IncrementActiveFrameCount() {
active_frame_count_++;
}
void SiteInstanceImpl::DecrementActiveFrameCount() {
- if (--active_frame_count_ == 0)
- FOR_EACH_OBSERVER(Observer, observers_, ActiveFrameCountIsZero(this));
+ if (--active_frame_count_ == 0) {
+ for (auto& observer : observers_)
+ observer.ActiveFrameCountIsZero(this);
+ }
}
void SiteInstanceImpl::IncrementRelatedActiveContentsCount() {
@@ -395,13 +401,15 @@ void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
void SiteInstanceImpl::RenderProcessWillExit(RenderProcessHost* host) {
// TODO(nick): http://crbug.com/575400 - RenderProcessWillExit might not serve
// any purpose here.
- FOR_EACH_OBSERVER(Observer, observers_, RenderProcessGone(this));
+ for (auto& observer : observers_)
+ observer.RenderProcessGone(this);
}
void SiteInstanceImpl::RenderProcessExited(RenderProcessHost* host,
base::TerminationStatus status,
int exit_code) {
- FOR_EACH_OBSERVER(Observer, observers_, RenderProcessGone(this));
+ for (auto& observer : observers_)
+ observer.RenderProcessGone(this);
}
void SiteInstanceImpl::LockToOrigin() {
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index 1a255ebb848..3b05af89bf1 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -49,6 +49,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
bool IsRelatedSiteInstance(const SiteInstance* instance) override;
size_t GetRelatedActiveContentsCount() override;
bool RequiresDedicatedProcess() override;
+ bool IsDefaultSubframeSiteInstance() const override;
// Returns the SiteInstance, related to this one, that should be used
// for subframes when an oopif is required, but a dedicated process is not.
@@ -100,10 +101,6 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- bool is_default_subframe_site_instance() {
- return is_default_subframe_site_instance_;
- }
-
// Sets the global factory used to create new RenderProcessHosts. It may be
// NULL, in which case the default RenderProcessHost will be created (this is
// the behavior if you don't call this function). The factory must be set
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index 895d9f753d2..2523cfc3479 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -165,7 +165,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
NavigationEntryImpl* e1 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
+ instance, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
// Redundantly setting e1's SiteInstance shouldn't affect the ref count.
@@ -175,7 +175,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Add a second reference
NavigationEntryImpl* e2 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
+ instance, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
instance = nullptr;
@@ -220,7 +220,7 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) {
std::unique_ptr<NavigationEntryImpl> e1 =
base::WrapUnique(new NavigationEntryImpl(
- SiteInstanceImpl::Create(nullptr), 0, url, Referrer(),
+ SiteInstanceImpl::Create(nullptr), url, Referrer(),
base::string16(), ui::PAGE_TRANSITION_LINK, false));
// Clone the entry.
@@ -813,8 +813,8 @@ TEST_F(SiteInstanceTest, DefaultSubframeSiteInstance) {
EXPECT_NE(main_instance, subframe_instance);
EXPECT_EQ(subframe_instance, main_instance->GetDefaultSubframeSiteInstance());
- EXPECT_FALSE(main_instance->is_default_subframe_site_instance());
- EXPECT_TRUE(subframe_instance->is_default_subframe_site_instance());
+ EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
+ EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
@@ -828,8 +828,8 @@ TEST_F(SiteInstanceTest, DefaultSubframeSiteInstance) {
// SiteInstance with a different ID from the original.
subframe_instance = main_instance->GetDefaultSubframeSiteInstance();
EXPECT_NE(subframe_instance->GetId(), subframe_instance_id);
- EXPECT_FALSE(main_instance->is_default_subframe_site_instance());
- EXPECT_TRUE(subframe_instance->is_default_subframe_site_instance());
+ EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
+ EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
EXPECT_EQ(subframe_instance->GetDefaultSubframeSiteInstance(),
subframe_instance);
EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 4808567c779..a7710cb2510 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -14,11 +14,13 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/path_service.h"
+#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_timeouts.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
@@ -41,6 +43,7 @@
#include "content/common/renderer.mojom.h"
#include "content/common/view_messages.h"
#include "content/public/browser/interstitial_page_delegate.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -50,23 +53,26 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
-#include "content/test/test_frame_navigation_observer.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_security_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "ui/display/display_switches.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/point.h"
+#include "ui/native_theme/native_theme_switches.h"
#if defined(USE_AURA)
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
@@ -257,7 +263,7 @@ void SurfaceHitTestTestHelper(
child_event.clickCount = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &child_event);
+ router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
EXPECT_EQ(23, child_frame_monitor.event().x);
@@ -275,7 +281,7 @@ void SurfaceHitTestTestHelper(
main_event.y = 1;
main_event.clickCount = 1;
// Ladies and gentlemen, THIS is the main_event!
- router->RouteMouseEvent(root_view, &main_event);
+ router->RouteMouseEvent(root_view, &main_event, ui::LatencyInfo());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
@@ -550,12 +556,17 @@ std::string SitePerProcessBrowserTest::DepictFrameTree(FrameTreeNode* node) {
void SitePerProcessBrowserTest::SetUpCommandLine(
base::CommandLine* command_line) {
IsolateAllSitesForTesting(command_line);
+#if !defined(OS_ANDROID)
+ // TODO(bokan): Needed for scrollability check in
+ // FrameOwnerPropertiesPropagationScrolling. crbug.com/662196.
+ command_line->AppendSwitch(switches::kDisableOverlayScrollbar);
+#endif
};
void SitePerProcessBrowserTest::SetUpOnMainThread() {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
//
@@ -578,6 +589,26 @@ class SitePerProcessHighDPIBrowserTest : public SitePerProcessBrowserTest {
}
};
+//
+// SitePerProcessNonIntegerScaleFactorBrowserTest
+//
+
+class SitePerProcessNonIntegerScaleFactorBrowserTest
+ : public SitePerProcessBrowserTest {
+ public:
+ const double kDeviceScaleFactor = 1.5;
+
+ SitePerProcessNonIntegerScaleFactorBrowserTest() {}
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ SitePerProcessBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(
+ switches::kForceDeviceScaleFactor,
+ base::StringPrintf("%f", kDeviceScaleFactor));
+ }
+};
+
// SitePerProcessIgnoreCertErrorsBrowserTest
class SitePerProcessIgnoreCertErrorsBrowserTest
@@ -624,24 +655,28 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
"a.com", "/cross_site_iframe_factory.html?a(b)"));
NavigateToURL(shell(), main_url);
- EXPECT_EQ(SitePerProcessHighDPIBrowserTest::kDeviceScaleFactor,
- GetFrameDeviceScaleFactor(web_contents()));
+ // On Android forcing device scale factor does not work for tests, therefore
+ // we ensure that make frame and iframe have the same DIP scale there, but
+ // not necessarily kDeviceScaleFactor.
+ const double expected_dip_scale =
+#if defined(OS_ANDROID)
+ GetFrameDeviceScaleFactor(web_contents());
+#else
+ SitePerProcessHighDPIBrowserTest::kDeviceScaleFactor;
+#endif
+
+ EXPECT_EQ(expected_dip_scale, GetFrameDeviceScaleFactor(web_contents()));
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
FrameTreeNode* child = root->child_at(0);
- EXPECT_EQ(SitePerProcessHighDPIBrowserTest::kDeviceScaleFactor,
- GetFrameDeviceScaleFactor(child));
+ EXPECT_EQ(expected_dip_scale, GetFrameDeviceScaleFactor(child));
}
// Ensure that navigating subframes in --site-per-process mode works and the
// correct documents are committed.
-#if defined(OS_WIN)
-// This test is flaky on Windows, see https://crbug.com/629419.
-#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)))"));
NavigateToURL(shell(), main_url);
@@ -677,7 +712,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
// Load cross-site page into iframe.
GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
- NavigateFrameToURL(root->child_at(0), url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(root->child_at(0), url);
+ deleted_observer.WaitUntilDeleted();
+ }
// Verify that the navigation succeeded and the expected URL was loaded.
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
@@ -721,7 +760,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
// Load another cross-site page into the same iframe.
url = embedded_test_server()->GetURL("bar.com", "/title3.html");
- NavigateFrameToURL(root->child_at(0), url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(root->child_at(0), url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
@@ -1244,7 +1287,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
nested_event.clickCount = 1;
nested_frame_monitor.ResetEventReceived();
main_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &nested_event);
+ router->RouteMouseEvent(root_view, &nested_event, ui::LatencyInfo());
EXPECT_TRUE(nested_frame_monitor.EventWasReceived());
EXPECT_EQ(21, nested_frame_monitor.event().x);
@@ -1309,7 +1352,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
child_event.clickCount = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &child_event);
+ router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_EQ(75, main_frame_monitor.event().x);
@@ -1394,7 +1437,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Send an initial MouseMove to the root view, which shouldn't affect the
// other renderers.
- web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event);
+ web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event,
+ ui::LatencyInfo());
EXPECT_TRUE(a_frame_monitor.EventWasReceived());
a_frame_monitor.ResetEventReceived();
EXPECT_FALSE(b_frame_monitor.EventWasReceived());
@@ -1405,7 +1449,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// A should receive a MouseMove event.
mouse_event.x = point_in_b_frame.x();
mouse_event.y = point_in_b_frame.y();
- web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event);
+ web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event,
+ ui::LatencyInfo());
EXPECT_TRUE(a_frame_monitor.EventWasReceived());
EXPECT_EQ(a_frame_monitor.event().type, blink::WebInputEvent::MouseMove);
a_frame_monitor.ResetEventReceived();
@@ -1418,7 +1463,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// other RenderWidgetHostView.
mouse_event.x = point_in_d_frame.x();
mouse_event.y = point_in_d_frame.y();
- web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event);
+ web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event,
+ ui::LatencyInfo());
EXPECT_TRUE(a_frame_monitor.EventWasReceived());
EXPECT_EQ(a_frame_monitor.event().type, blink::WebInputEvent::MouseMove);
EXPECT_TRUE(b_frame_monitor.EventWasReceived());
@@ -1481,7 +1527,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
mouse_event.clickCount = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_FALSE(main_frame_monitor.EventWasReceived());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -1496,12 +1542,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// the first time, because the first MouseMove to the child frame
// causes a MouseMove to be sent to the main frame also, which we
// need to ignore.
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
mouse_event.x = 1;
mouse_event.y = 2;
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_FALSE(main_frame_monitor.EventWasReceived());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -1513,7 +1559,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
mouse_event.y = 75;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_FALSE(main_frame_monitor.EventWasReceived());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -1524,12 +1570,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
mouse_event.x = 1;
mouse_event.y = 3;
// Sending the MouseMove twice for the same reason as above.
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
mouse_event.x = 1;
mouse_event.y = 4;
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
@@ -1540,7 +1586,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
mouse_event.y = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
@@ -1553,7 +1599,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
mouse_event.y = 75;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &mouse_event);
+ router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
@@ -1561,14 +1607,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Tests OOPIF rendering by checking that the RWH of the iframe generates
// OnSwapCompositorFrame message.
-#if defined(OS_ANDROID)
-// http://crbug.com/471850
-#define MAYBE_CompositorFrameSwapped DISABLED_CompositorFrameSwapped
-#else
-#define MAYBE_CompositorFrameSwapped CompositorFrameSwapped
-#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- MAYBE_CompositorFrameSwapped) {
+ CompositorFrameSwapped) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(baz)"));
NavigateToURL(shell(), main_url);
@@ -1718,13 +1758,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RestrictFrameDetach) {
DepictFrameTree(root));
}
-#if defined(OS_WIN)
-// This test is flaky on Windows, see https://crbug.com/629419.
-#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)))"));
NavigateToURL(shell(), main_url);
@@ -1743,7 +1777,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
// Load cross-site page into iframe.
GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
- NavigateFrameToURL(root->child_at(0), url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(root->child_at(0), url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
@@ -1764,7 +1802,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
// Emulate the main frame changing the src of the iframe such that it
// navigates cross-site.
url = embedded_test_server()->GetURL("bar.com", "/title3.html");
- NavigateIframeToURL(shell()->web_contents(), "child-0", url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateIframeToURL(shell()->web_contents(), "child-0", url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
@@ -1783,7 +1825,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
// Navigate back to the parent's origin and ensure we return to the
// parent's process.
- NavigateFrameToURL(child, http_url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(child, http_url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(http_url, observer.last_navigation_url());
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
@@ -1974,6 +2020,40 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(site_b_url, observer.last_navigation_url());
}
+// This test ensures that WebContentsImpl::FocusOwningWebContents does not crash
+// the browser if the currently focused frame's renderer has disappeared.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RemoveFocusFromKilledFrame) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "foo.com", "/cross_site_iframe_factory.html?foo.com(bar.com)"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ TestNavigationObserver observer(shell()->web_contents());
+ ASSERT_EQ(1U, root->child_count());
+
+ // Make sure node2 points to the correct cross-site page.
+ GURL site_b_url = embedded_test_server()->GetURL(
+ "bar.com", "/cross_site_iframe_factory.html?bar.com()");
+ FrameTreeNode* node2 = root->child_at(0);
+ EXPECT_EQ(site_b_url, node2->current_url());
+
+ web_contents()->SetFocusedFrame(
+ node2, node2->current_frame_host()->GetSiteInstance());
+
+ // Kill that cross-site renderer.
+ RenderProcessHost* child_process = node2->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0, false);
+ crash_observer.Wait();
+
+ // Try to focus the root's owning WebContents.
+ web_contents()->FocusOwningWebContents(
+ root->current_frame_host()->GetRenderWidgetHost());
+}
+
// This test is similar to
// SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess with
// addition that node2 also has a cross-origin frame to site C.
@@ -2967,6 +3047,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that "scrolling" property on frame elements propagates to child frames
// correctly.
// Does not work on android since android has scrollbars overlayed.
+// TODO(bokan): Pretty soon most/all platforms will use overlay scrollbars. This
+// test should find a better way to check for scrollability. crbug.com/662196.
#if defined(OS_ANDROID)
#define MAYBE_FrameOwnerPropertiesPropagationScrolling \
DISABLED_FrameOwnerPropertiesPropagationScrolling
@@ -4249,13 +4331,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) {
EXPECT_EQ(1, GetReceivedMessages(child2));
}
-#if defined(OS_WIN)
-// This test is flaky on Windows, see https://crbug.com/629419.
-#define MAYBE_RFPHDestruction DISABLED_RFPHDestruction
-#else
-#define MAYBE_RFPHDestruction RFPHDestruction
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RFPHDestruction) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RFPHDestruction) {
GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
NavigateToURL(shell(), main_url);
@@ -4267,7 +4343,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RFPHDestruction) {
// Load cross-site page into iframe.
FrameTreeNode* child = root->child_at(0);
GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
- NavigateFrameToURL(root->child_at(0), url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(root->child_at(0), url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
EXPECT_EQ(
@@ -4283,7 +4363,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RFPHDestruction) {
// Load another cross-site page.
url = embedded_test_server()->GetURL("bar.com", "/title3.html");
- NavigateIframeToURL(shell()->web_contents(), "test", url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateIframeToURL(shell()->web_contents(), "test", url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(url, observer.last_navigation_url());
EXPECT_EQ(
@@ -4298,14 +4382,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RFPHDestruction) {
DepictFrameTree(root));
// Navigate back to the parent's origin.
- RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
- url = embedded_test_server()->GetURL("/title1.html");
- NavigateFrameToURL(child, url);
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ url = embedded_test_server()->GetURL("/title1.html");
+ NavigateFrameToURL(child, url);
+ // Wait for the old process to exit, to verify that the proxies go away.
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(url, observer.last_navigation_url());
EXPECT_TRUE(observer.last_navigation_succeeded());
- // Wait for the old process to exit, to verify that the proxies go away.
- deleted_observer.WaitUntilDeleted();
EXPECT_EQ(
" Site A\n"
" |--Site A\n"
@@ -5179,8 +5265,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- web_contents()->GetInputEventRouter()->RouteMouseEvent(root_view,
- &mouse_event);
+ web_contents()->GetInputEventRouter()->RouteMouseEvent(
+ root_view, &mouse_event, ui::LatencyInfo());
// CursorMessageFilter::Wait() implicitly tests whether we receive a
// ViewHostMsg_SetCursor message from the renderer process, because it does
@@ -5705,13 +5791,13 @@ void CreateContextMenuTestHelper(
click_event.x = point.x();
click_event.y = point.y();
click_event.clickCount = 1;
- router->RouteMouseEvent(root_view, &click_event);
+ router->RouteMouseEvent(root_view, &click_event, ui::LatencyInfo());
// We also need a MouseUp event, needed by Windows.
click_event.type = blink::WebInputEvent::MouseUp;
click_event.x = point.x();
click_event.y = point.y();
- router->RouteMouseEvent(root_view, &click_event);
+ router->RouteMouseEvent(root_view, &click_event, ui::LatencyInfo());
context_menu_delegate.Wait();
@@ -6077,10 +6163,16 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(1, child_count);
}
+#if defined(OS_LINUX)
+#define MAYBE_NavigateAboutBlankAndDetach DISABLED_NavigateAboutBlankAndDetach
+#else
+#define MAYBE_NavigateAboutBlankAndDetach NavigateAboutBlankAndDetach
+#endif
// Similar to NavigateProxyAndDetachBeforeCommit, but uses a synchronous
// navigation to about:blank and the parent removes the child frame in a load
// event handler for the subframe.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateAboutBlankAndDetach) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_NavigateAboutBlankAndDetach) {
GURL main_url(
embedded_test_server()->GetURL("a.com", "/remove_frame_on_load.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -6145,7 +6237,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Send the message to create a proxy for B's new child frame in A. This
// used to crash, as parent_routing_id refers to a proxy that doesn't exist
// anymore.
- RenderProcessHostImpl::GetRendererInterface(process_a)->CreateFrameProxy(
+ process_a->GetRendererInterface()->CreateFrameProxy(
new_routing_id, view_routing_id, MSG_ROUTING_NONE, parent_routing_id,
FrameReplicationState());
@@ -6221,8 +6313,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
params->widget_params->hidden = true;
params->replication_state.name = "name";
params->replication_state.unique_name = "name";
- RenderProcessHostImpl::GetRendererInterface(process)->CreateFrame(
- std::move(params));
+ process->GetRendererInterface()->CreateFrame(std::move(params));
}
// The test must wait for the process to exit, but if there is no leak, the
@@ -6287,8 +6378,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ParentDetachRemoteChild) {
params->widget_params->hidden = true;
params->replication_state.name = "name";
params->replication_state.unique_name = "name";
- RenderProcessHostImpl::GetRendererInterface(process)->CreateFrame(
- std::move(params));
+ process->GetRendererInterface()->CreateFrame(std::move(params));
}
// The test must wait for the process to exit, but if there is no leak, the
@@ -6579,8 +6669,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
MAYBE_PassiveMixedContentInIframe) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
+ ASSERT_TRUE(https_server.Start());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -6588,20 +6678,26 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
GURL iframe_url(
https_server.GetURL("/mixed-content/basic-passive-in-iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url));
- EXPECT_TRUE(web_contents->DisplayedInsecureContent());
+ NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+ EXPECT_TRUE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
// When the subframe navigates, the WebContents should still be marked
// as having displayed insecure content.
GURL navigate_url(https_server.GetURL("/title1.html"));
FrameTreeNode* root = web_contents->GetFrameTree()->root();
NavigateFrameToURL(root->child_at(0), navigate_url);
- EXPECT_TRUE(web_contents->DisplayedInsecureContent());
+ entry = web_contents->GetController().GetVisibleEntry();
+ EXPECT_TRUE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
// When the main frame navigates, it should no longer be marked as
// displaying insecure content.
EXPECT_TRUE(
NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
- EXPECT_FALSE(web_contents->DisplayedInsecureContent());
+ entry = web_contents->GetController().GetVisibleEntry();
+ EXPECT_FALSE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
}
// Tests that, when a parent frame is set to strictly block mixed
@@ -6611,8 +6707,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
PassiveMixedContentInIframeWithStrictBlocking) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
+ ASSERT_TRUE(https_server.Start());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -6620,7 +6716,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
GURL iframe_url_with_strict_blocking(https_server.GetURL(
"/mixed-content/basic-passive-in-iframe-with-strict-blocking.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url_with_strict_blocking));
- EXPECT_FALSE(web_contents->DisplayedInsecureContent());
+ NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+ EXPECT_FALSE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
FrameTreeNode* root = web_contents->GetFrameTree()->root();
EXPECT_EQ(blink::kBlockAllMixedContent,
@@ -6653,8 +6751,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
PassiveMixedContentInIframeWithUpgrade) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
+ ASSERT_TRUE(https_server.Start());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -6662,7 +6760,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
GURL iframe_url_with_upgrade(https_server.GetURL(
"/mixed-content/basic-passive-in-iframe-with-upgrade.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url_with_upgrade));
- EXPECT_FALSE(web_contents->DisplayedInsecureContent());
+ NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+ EXPECT_FALSE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_INSECURE_CONTENT));
FrameTreeNode* root = web_contents->GetFrameTree()->root();
EXPECT_EQ(blink::kUpgradeInsecureRequests,
@@ -6697,8 +6797,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
ActiveMixedContentInIframe) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
+ ASSERT_TRUE(https_server.Start());
GURL iframe_url(
https_server.GetURL("/mixed-content/basic-active-in-iframe.html"));
@@ -6722,8 +6822,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
SubresourceWithCertificateErrors) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
+ ASSERT_TRUE(https_server.Start());
GURL url(https_server.GetURL(
"example.test",
@@ -6735,14 +6835,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
ASSERT_TRUE(entry);
// The main page was loaded with certificate errors.
- EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN,
- entry->GetSSL().security_style);
+ EXPECT_TRUE(net::IsCertStatusError(entry->GetSSL().cert_status));
// The image that the iframe loaded had certificate errors also, so
// the page should be marked as having displayed subresources with
// cert errors.
- EXPECT_TRUE(entry->GetSSL().content_status &
- SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS);
+ EXPECT_TRUE(!!(entry->GetSSL().content_status &
+ SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS));
}
// Test setting a cross-origin iframe to display: none.
@@ -7105,6 +7204,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
"parent.location = '%s');",
b_url.spec().c_str());
+ // Ensure the child has received a user gesture, so that it has permission
+ // to framebust.
+ SimulateMouseClick(
+ root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), 1, 1);
TestFrameNavigationObserver frame_observer(root);
EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
frame_observer.Wait();
@@ -7952,7 +8055,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL stall_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
TestNavigationManager delayer(shell()->web_contents(), stall_url);
shell()->LoadURL(stall_url);
- EXPECT_TRUE(delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(delayer.WaitForRequestStart());
// The pending RFH should be in the same process as the popup.
RenderFrameHostImpl* pending_rfh =
@@ -8014,7 +8117,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL stall_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
TestNavigationManager delayer(shell()->web_contents(), stall_url);
shell()->LoadURL(stall_url);
- EXPECT_TRUE(delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(delayer.WaitForRequestStart());
// Kill the b.com process, currently in use by the pending RenderFrameHost
// and the popup.
@@ -8305,4 +8408,329 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateInUnloadHandler) {
DepictFrameTree(root));
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ RFHTransfersWhilePendingDeletion) {
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Start a cross-process navigation and wait until the response is received.
+ GURL cross_site_url_1 =
+ embedded_test_server()->GetURL("b.com", "/title1.html");
+ TestNavigationManager cross_site_manager(shell()->web_contents(),
+ cross_site_url_1);
+ shell()->web_contents()->GetController().LoadURL(
+ cross_site_url_1, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ EXPECT_TRUE(cross_site_manager.WaitForResponse());
+
+ // Start a renderer-initiated navigation to a cross-process url and make sure
+ // the navigation will be blocked before being transferred.
+ GURL cross_site_url_2 =
+ embedded_test_server()->GetURL("c.com", "/title1.html");
+ TestNavigationManager transfer_manager(shell()->web_contents(),
+ cross_site_url_2);
+ EXPECT_TRUE(ExecuteScript(
+ root, "location.href = '" + cross_site_url_2.spec() + "';"));
+ EXPECT_TRUE(transfer_manager.WaitForResponse());
+
+ // Now have the cross-process navigation commit and mark the current RFH as
+ // pending deletion.
+ cross_site_manager.WaitForNavigationFinished();
+
+ // Resume the navigation in the previous RFH that has just been marked as
+ // pending deletion. We should not crash.
+ transfer_manager.WaitForNavigationFinished();
+}
+
+class NavigationHandleWatcher : public WebContentsObserver {
+ public:
+ NavigationHandleWatcher(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+ void DidStartNavigation(NavigationHandle* navigation_handle) override {
+ DCHECK_EQ(GURL("http://b.com/"),
+ navigation_handle->GetStartingSiteInstance()->GetSiteURL());
+ }
+};
+
+// Verifies that the SiteInstance of a NavigationHandle correctly identifies the
+// RenderFrameHost that started the navigation (and not the destination RFH).
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ NavigationHandleSiteInstance) {
+ // Navigate to a page with a cross-site iframe.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Navigate the iframe cross-site.
+ NavigationHandleWatcher watcher(shell()->web_contents());
+ TestNavigationObserver load_observer(shell()->web_contents());
+ GURL frame_url = embedded_test_server()->GetURL("c.com", "/title1.html");
+ EXPECT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ "window.frames[0].location = \"" + frame_url.spec() + "\";"));
+ load_observer.Wait();
+}
+
+// Test that when canceling a pending RenderFrameHost in the middle of a
+// redirect, and then killing the corresponding RenderView's renderer process,
+// the RenderViewHost isn't reused in an improper state later. Previously this
+// led to a crash in CreateRenderView when recreating the RenderView due to a
+// stale main frame routing ID. See https://crbug.com/627400.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReuseNonLiveRenderViewHostAfterCancelPending) {
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), a_url));
+
+ // Open a popup and navigate it to b.com.
+ Shell* popup = OpenPopup(shell(), a_url, "popup");
+ EXPECT_TRUE(NavigateToURL(popup, b_url));
+
+ // Open a second popup and navigate it to b.com, which redirects to c.com.
+ // The navigation to b.com will create a pending RenderFrameHost, which will
+ // be canceled during the redirect to c.com. Note that NavigateToURL will
+ // return false because the committed URL won't match the requested URL due
+ // to the redirect.
+ Shell* popup2 = OpenPopup(shell(), a_url, "popup2");
+ TestNavigationObserver observer(popup2->web_contents());
+ GURL redirect_url(embedded_test_server()->GetURL(
+ "b.com", "/server-redirect?" + c_url.spec()));
+ EXPECT_FALSE(NavigateToURL(popup2, redirect_url));
+ EXPECT_EQ(c_url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ // Kill the b.com process (which currently hosts a RenderFrameProxy that
+ // replaced the pending RenderFrame in |popup2|, as well as the RenderFrame
+ // for |popup|).
+ RenderProcessHost* b_process =
+ popup->web_contents()->GetMainFrame()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ b_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ b_process->Shutdown(0, false);
+ crash_observer.Wait();
+
+ // Navigate the second popup to b.com. This used to crash when creating the
+ // RenderView, because it reused the RenderViewHost created by the canceled
+ // navigation to b.com, and that RenderViewHost had a stale main frame
+ // routing ID and active state.
+ EXPECT_TRUE(NavigateToURL(popup2, b_url));
+}
+
+// Check that after a pending RFH is canceled and replaced with a proxy (which
+// reuses the canceled RFH's RenderViewHost), navigating to a main frame in the
+// same site as the canceled RFH doesn't lead to a renderer crash. The steps
+// here are similar to ReuseNonLiveRenderViewHostAfterCancelPending, but don't
+// involve crashing the renderer. See https://crbug.com/651980.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ RecreateMainFrameAfterCancelPending) {
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), a_url));
+
+ // Open a popup and navigate it to b.com.
+ Shell* popup = OpenPopup(shell(), a_url, "popup");
+ EXPECT_TRUE(NavigateToURL(popup, b_url));
+
+ // Open a second popup and navigate it to b.com, which redirects to c.com.
+ // The navigation to b.com will create a pending RenderFrameHost, which will
+ // be canceled during the redirect to c.com. Note that NavigateToURL will
+ // return false because the committed URL won't match the requested URL due
+ // to the redirect.
+ Shell* popup2 = OpenPopup(shell(), a_url, "popup2");
+ TestNavigationObserver observer(popup2->web_contents());
+ GURL redirect_url(embedded_test_server()->GetURL(
+ "b.com", "/server-redirect?" + c_url.spec()));
+ EXPECT_FALSE(NavigateToURL(popup2, redirect_url));
+ EXPECT_EQ(c_url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ // Navigate the second popup to b.com. This used to crash the b.com renderer
+ // because it failed to delete the canceled RFH's RenderFrame, so this caused
+ // it to try to create a frame widget which already existed.
+ EXPECT_TRUE(NavigateToURL(popup2, b_url));
+}
+
+// Check that when a pending RFH is canceled and a proxy needs to be created in
+// its place, the proxy is properly initialized on the renderer side. See
+// https://crbug.com/653746.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CommunicateWithProxyAfterCancelPending) {
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), a_url));
+
+ // Open a popup and navigate it to b.com.
+ Shell* popup = OpenPopup(shell(), a_url, "popup");
+ EXPECT_TRUE(NavigateToURL(popup, b_url));
+
+ // Open a second popup and navigate it to b.com, which redirects to c.com.
+ // The navigation to b.com will create a pending RenderFrameHost, which will
+ // be canceled during the redirect to c.com. Note that NavigateToURL will
+ // return false because the committed URL won't match the requested URL due
+ // to the redirect.
+ Shell* popup2 = OpenPopup(shell(), a_url, "popup2");
+ TestNavigationObserver observer(popup2->web_contents());
+ GURL redirect_url(embedded_test_server()->GetURL(
+ "b.com", "/server-redirect?" + c_url.spec()));
+ EXPECT_FALSE(NavigateToURL(popup2, redirect_url));
+ EXPECT_EQ(c_url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ // Because b.com has other active frames (namely, the frame in |popup|),
+ // there should be a proxy created for the canceled RFH, and it should be
+ // live.
+ SiteInstance* b_instance = popup->web_contents()->GetSiteInstance();
+ FrameTreeNode* popup2_root =
+ static_cast<WebContentsImpl*>(popup2->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderFrameProxyHost* proxy =
+ popup2_root->render_manager()->GetRenderFrameProxyHost(b_instance);
+ EXPECT_TRUE(proxy);
+ EXPECT_TRUE(proxy->is_render_frame_proxy_live());
+
+ // Add a postMessage listener in |popup2| (currently at a c.com URL).
+ EXPECT_TRUE(
+ ExecuteScript(popup2,
+ "window.addEventListener('message', function(event) {\n"
+ " document.title=event.data;\n"
+ "});"));
+
+ // Check that a postMessage can be sent via |proxy| above. This needs to be
+ // done from the b.com process. |popup| is currently in b.com, but it can't
+ // reach the window reference for |popup2| due to a security restriction in
+ // Blink. So, navigate the main tab to b.com and then send a postMessage to
+ // |popup2|. This is allowed since the main tab is |popup2|'s opener.
+ EXPECT_TRUE(NavigateToURL(shell(), b_url));
+
+ base::string16 expected_title(base::UTF8ToUTF16("foo"));
+ TitleWatcher title_watcher(popup2->web_contents(), expected_title);
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "window.open('','popup2').postMessage('foo', '*');"));
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+}
+
+// Checks that everything is cleaned up even when the frame tree is destroyed
+// during a transfer. See also https://crbug.com/657195.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FrameTreeDestroyedInMiddleOfTransfer) {
+ // Transfer navigations don't occur with PlzNavigate.
+ if (IsBrowserSideNavigationEnabled())
+ return;
+ GURL page_url(embedded_test_server()->GetURL(
+ "main.com", "/frame_tree/page_with_one_frame.html"));
+ GURL initial_frame_url(embedded_test_server()->GetURL(
+ "main.com", "/cross-site/baz.com/title1.html"));
+
+ {
+ // Navigation below is needed to make OpenPopup (next statement) work.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
+
+ // Create a separate Shell + WebContents - these will be destroyed during
+ // the test at a very special moment.
+ Shell* other_shell = OpenPopup(shell()->web_contents(), GURL(), "popup");
+
+ // Load the test page, while monitoring navigations of the frame (to catch
+ // when the frame navigation will initiate a transfer to another renderer).
+ TestNavigationManager navigation_manager(other_shell->web_contents(),
+ initial_frame_url);
+ other_shell->LoadURL(page_url);
+
+ // Wait until |navigation_manager| detects a WillProcessResponse associated
+ // with the frame navigation.
+ ASSERT_TRUE(navigation_manager.WaitForResponse());
+
+ // At this point we have almost (but not quite) triggered a transfer
+ // request. The transfer will be initiated when resuming the navigation.
+ // Posting a task to destroy the frame being navigated means that the
+ // destruction won't happen now, but will happen right after initiating the
+ // transfer AND before the transfer completes. i.e. This task will be
+ // executed on the message queue before the task to process the
+ // DidStartProvisionalLoad IPC from the renderer.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&WebContents::Close,
+ base::Unretained(other_shell->web_contents())));
+
+ // Resume the navigation. This will 1) initiate the transfer and 2) shortly
+ // after destroy the |other_shell| via WebContents::Close task posted above.
+ // Destroying the NavigationHandle at this special moment used to trigger
+ // https://crbug.com/657195.
+ navigation_manager.WaitForNavigationFinished();
+ }
+
+ // Start a URLRequest to the same URL. This should succeed. This would have
+ // hit the 20 seconds delay before https://crbug.com/657195 was fixed.
+ EXPECT_TRUE(NavigateToURL(shell(), page_url));
+ EXPECT_EQ(page_url, shell()->web_contents()->GetLastCommittedURL());
+
+ // Note: even if the test fails and for some reason, the test has not timed
+ // out by this point, the test teardown code will still hit a DCHECK when it
+ // calls AssertNoURLRequests() in the shell's URLRequestContext destructor.
+}
+
+// Test that MouseDown and MouseUp to the same coordinates do not result in
+// different coordinates after routing. See bug https://crbug.com/670253.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_MouseClickWithNonIntegerScaleFactor \
+ DISABLED_MouseClickWithNonIntegerScaleFactor
+#else
+#define MAYBE_MouseClickWithNonIntegerScaleFactor \
+ MouseClickWithNonIntegerScaleFactor
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessNonIntegerScaleFactorBrowserTest,
+ MAYBE_MouseClickWithNonIntegerScaleFactor) {
+ GURL initial_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), initial_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ // Create listener for input events.
+ RenderWidgetHostMouseEventMonitor event_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+
+ blink::WebMouseEvent mouse_event;
+ mouse_event.type = blink::WebInputEvent::MouseDown;
+ mouse_event.button = blink::WebPointerProperties::Button::Left;
+ mouse_event.x = 75;
+ mouse_event.y = 75;
+ mouse_event.clickCount = 1;
+ event_monitor.ResetEventReceived();
+ router->RouteMouseEvent(rwhv, &mouse_event, ui::LatencyInfo());
+
+ EXPECT_TRUE(event_monitor.EventWasReceived());
+ gfx::Point mouse_down_coords =
+ gfx::Point(event_monitor.event().x, event_monitor.event().y);
+ event_monitor.ResetEventReceived();
+
+ mouse_event.type = blink::WebInputEvent::MouseUp;
+ mouse_event.x = 75;
+ mouse_event.y = 75;
+ router->RouteMouseEvent(rwhv, &mouse_event, ui::LatencyInfo());
+
+ EXPECT_TRUE(event_monitor.EventWasReceived());
+ EXPECT_EQ(mouse_down_coords,
+ gfx::Point(event_monitor.event().x, event_monitor.event().y));
+}
+
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_error_handler.h b/chromium/content/browser/ssl/ssl_error_handler.h
index d00a43ba869..03a11eac80e 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.h
+++ b/chromium/content/browser/ssl/ssl_error_handler.h
@@ -22,8 +22,6 @@ class URLRequest;
namespace content {
-class ResourceDispatcherHostImpl;
-class SSLManager;
class WebContents;
// SSLErrorHandler is the UI-thread class for handling SSL certificate
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index bc38ee4b0c4..c9cf39e41a3 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -16,14 +16,12 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/security_style_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/ssl_host_state_delegate.h"
-#include "content/public/browser/ssl_status.h"
#include "net/url_request/url_request.h"
namespace content {
@@ -152,17 +150,6 @@ void SSLManager::OnSSLCertificateSubresourceError(
ssl_info, fatal);
}
-// static
-void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
- SSLManagerSet* managers = static_cast<SSLManagerSet*>(
- context->GetUserData(kSSLManagerKeyName));
-
- for (std::set<SSLManager*>::iterator i = managers->get().begin();
- i != managers->get().end(); ++i) {
- (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry());
- }
-}
-
SSLManager::SSLManager(NavigationControllerImpl* controller)
: controller_(controller),
ssl_host_state_delegate_(
@@ -186,13 +173,51 @@ SSLManager::~SSLManager() {
void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
- UpdateEntry(entry);
+ int content_status_flags = 0;
+ 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
+ // clear because of a frame navigation.)
+ NavigationEntryImpl* previous_entry =
+ controller_->GetEntryAtIndex(details.previous_entry_index);
+ if (previous_entry) {
+ content_status_flags = previous_entry->GetSSL().content_status;
+ }
+ }
+ 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::DidRunInsecureContent(const GURL& security_origin) {
+void SSLManager::DidDisplayMixedContent() {
+ UpdateLastCommittedEntry(SSLStatus::DISPLAYED_INSECURE_CONTENT, 0);
+}
+
+void SSLManager::DidDisplayContentWithCertErrors() {
+ NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
+ if (!entry)
+ return;
+ // Only record information about subresources with cert errors if the
+ // main page is HTTPS with a certificate.
+ if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
+ UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS, 0);
+ }
+}
+
+void SSLManager::DidShowPasswordInputOnHttp() {
+ UpdateLastCommittedEntry(SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP, 0);
+}
+
+void SSLManager::DidHideAllPasswordInputsOnHttp() {
+ UpdateLastCommittedEntry(0, SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+}
+
+void SSLManager::DidShowCreditCardInputOnHttp() {
+ UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP, 0);
+}
+
+void SSLManager::DidRunMixedContent(const GURL& security_origin) {
NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
if (!entry)
return;
@@ -206,7 +231,7 @@ void SSLManager::DidRunInsecureContent(const GURL& security_origin) {
security_origin.host(), site_instance->GetProcess()->GetID(),
SSLHostStateDelegate::MIXED_CONTENT);
}
- UpdateEntry(entry);
+ UpdateEntry(entry, 0, 0);
NotifySSLInternalStateChanged(controller_->GetBrowserContext());
}
@@ -224,7 +249,7 @@ void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) {
security_origin.host(), site_instance->GetProcess()->GetID(),
SSLHostStateDelegate::CERT_ERRORS_CONTENT);
}
- UpdateEntry(entry);
+ UpdateEntry(entry, 0, 0);
NotifySSLInternalStateChanged(controller_->GetBrowserContext());
}
@@ -336,66 +361,68 @@ void SSLManager::OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
ssl_host_state_delegate_));
}
-void SSLManager::UpdateEntry(NavigationEntryImpl* entry) {
+void 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;
SSLStatus original_ssl_status = entry->GetSSL(); // Copy!
-
- // Initialize the entry with an initial SecurityStyle if needed.
- if (entry->GetSSL().security_style == SECURITY_STYLE_UNKNOWN) {
- entry->GetSSL().security_style = GetSecurityStyleForResource(
- entry->GetURL(), !!entry->GetSSL().certificate,
- entry->GetSSL().cert_status);
- }
-
- WebContentsImpl* web_contents_impl =
- static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
- if (entry->GetSSL().security_style == SECURITY_STYLE_UNAUTHENTICATED)
- return;
-
- // Update the entry's flags for insecure content.
- if (!web_contents_impl->DisplayedInsecureContent())
- entry->GetSSL().content_status &= ~SSLStatus::DISPLAYED_INSECURE_CONTENT;
- if (web_contents_impl->DisplayedInsecureContent())
- entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT;
- if (!web_contents_impl->DisplayedContentWithCertErrors())
- entry->GetSSL().content_status &=
- ~SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
- if (web_contents_impl->DisplayedContentWithCertErrors())
- entry->GetSSL().content_status |=
- SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
+ entry->GetSSL().initialized = true;
+ entry->GetSSL().content_status |= add_content_status_flags;
+ entry->GetSSL().content_status &= ~remove_content_status_flags;
SiteInstance* site_instance = entry->site_instance();
// Note that |site_instance| can be NULL here because NavigationEntries don't
// necessarily have site instances. Without a process, the entry can't
- // possibly have insecure content. See bug http://crbug.com/12423.
- if (site_instance && ssl_host_state_delegate_ &&
- ssl_host_state_delegate_->DidHostRunInsecureContent(
- entry->GetURL().host(), site_instance->GetProcess()->GetID(),
- SSLHostStateDelegate::MIXED_CONTENT)) {
- entry->GetSSL().security_style = SECURITY_STYLE_AUTHENTICATION_BROKEN;
- entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT;
- }
+ // possibly have insecure content. See bug https://crbug.com/12423.
+ if (site_instance && ssl_host_state_delegate_) {
+ std::string host = entry->GetURL().host();
+ int process_id = site_instance->GetProcess()->GetID();
+ if (ssl_host_state_delegate_->DidHostRunInsecureContent(
+ host, process_id, SSLHostStateDelegate::MIXED_CONTENT)) {
+ entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT;
+ }
- if (site_instance && ssl_host_state_delegate_ &&
- ssl_host_state_delegate_->DidHostRunInsecureContent(
- entry->GetURL().host(), site_instance->GetProcess()->GetID(),
- SSLHostStateDelegate::CERT_ERRORS_CONTENT)) {
- entry->GetSSL().security_style = SECURITY_STYLE_AUTHENTICATION_BROKEN;
- entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS;
+ // Only record information about subresources with cert errors if the
+ // main page is HTTPS with a certificate.
+ if (entry->GetURL().SchemeIsCryptographic() &&
+ entry->GetSSL().certificate &&
+ ssl_host_state_delegate_->DidHostRunInsecureContent(
+ host, process_id, SSLHostStateDelegate::CERT_ERRORS_CONTENT)) {
+ entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS;
+ }
}
if (!entry->GetSSL().Equals(original_ssl_status))
NotifyDidChangeVisibleSSLState();
}
+void SSLManager::UpdateLastCommittedEntry(int add_content_status_flags,
+ int remove_content_status_flags) {
+ NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
+ if (!entry)
+ return;
+ UpdateEntry(entry, add_content_status_flags, remove_content_status_flags);
+}
+
void SSLManager::NotifyDidChangeVisibleSSLState() {
WebContentsImpl* contents =
static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
- contents->DidChangeVisibleSSLState();
+ contents->DidChangeVisibleSecurityState();
+}
+
+// static
+void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
+ SSLManagerSet* managers =
+ static_cast<SSLManagerSet*>(context->GetUserData(kSSLManagerKeyName));
+
+ for (std::set<SSLManager*>::iterator i = managers->get().begin();
+ i != managers->get().end(); ++i) {
+ (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry(), 0, 0);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_manager.h b/chromium/content/browser/ssl/ssl_manager.h
index 99d9845c62a..f135133efdf 100644
--- a/chromium/content/browser/ssl/ssl_manager.h
+++ b/chromium/content/browser/ssl/ssl_manager.h
@@ -13,6 +13,7 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/ssl_status.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "url/gurl.h"
@@ -62,9 +63,6 @@ class CONTENT_EXPORT SSLManager {
const net::SSLInfo& ssl_info,
bool fatal);
- // Called when SSL state for a host or tab changes.
- static void NotifySSLInternalStateChanged(BrowserContext* context);
-
// Construct an SSLManager for the specified tab.
explicit SSLManager(NavigationControllerImpl* controller);
virtual ~SSLManager();
@@ -78,10 +76,17 @@ class CONTENT_EXPORT SSLManager {
bool has_certificate,
net::CertStatus ssl_cert_status);
- // Entry point for insecure mixed content (loaded over HTTP).
- void DidRunInsecureContent(const GURL& security_origin);
-
- // Entry point for content loaded with HTTPS certificate errors.
+ // The following methods are called when a page includes insecure
+ // content. These methods update the SSLStatus on the NavigationEntry
+ // appropriately. If the result could change the visible SSL state,
+ // they notify the WebContents of the change via
+ // DidChangeVisibleSecurityState();
+ void DidDisplayMixedContent();
+ void DidDisplayContentWithCertErrors();
+ void DidShowPasswordInputOnHttp();
+ void DidHideAllPasswordInputsOnHttp();
+ void DidShowCreditCardInputOnHttp();
+ void DidRunMixedContent(const GURL& security_origin);
void DidRunContentWithCertErrors(const GURL& security_origin);
// An error occurred with the certificate in an SSL connection.
@@ -107,14 +112,29 @@ class CONTENT_EXPORT SSLManager {
void OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
int options_mask);
- // Updates the NavigationEntry with our current state. This 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.) This method will notify the WebContents of an SSL state
+ // change if a change was actually made.
+ void UpdateEntry(NavigationEntryImpl* entry,
+ int add_content_status_flags,
+ int remove_content_status_flags);
+
+ // Helper function for UpdateEntry().
+ void UpdateLastCommittedEntry(int add_content_status_flags,
+ int remove_content_status_flags);
// Notifies the WebContents that the SSL state changed.
void NotifyDidChangeVisibleSSLState();
+ // Updates the last committed entries of all |context|'s
+ // SSLManagers. Notifies each WebContents of visible SSL state changes
+ // if necessary.
+ static void NotifySSLInternalStateChanged(BrowserContext* context);
+
// The NavigationController that owns this SSLManager. We are responsible
// for the security UI of this tab.
NavigationControllerImpl* controller_;
diff --git a/chromium/content/browser/ssl/ssl_manager_unittest.cc b/chromium/content/browser/ssl/ssl_manager_unittest.cc
new file mode 100644
index 00000000000..cd910452bce
--- /dev/null
+++ b/chromium/content/browser/ssl/ssl_manager_unittest.cc
@@ -0,0 +1,106 @@
+// 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/ssl/ssl_manager.h"
+
+#include "base/macros.h"
+#include "content/browser/site_instance_impl.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"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/test/test_web_contents.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// A WebContentsDelegate that exposes the visible SSLStatus at the time
+// of the last VisibleSecurityStateChanged() call.
+class TestWebContentsDelegate : public WebContentsDelegate {
+ public:
+ TestWebContentsDelegate() : WebContentsDelegate() {}
+ ~TestWebContentsDelegate() override {}
+
+ const SSLStatus& last_ssl_state() { return last_ssl_state_; }
+
+ // WebContentsDelegate:
+ void VisibleSecurityStateChanged(WebContents* source) override {
+ NavigationEntry* entry = source->GetController().GetVisibleEntry();
+ EXPECT_TRUE(entry);
+ last_ssl_state_ = entry->GetSSL();
+ }
+
+ private:
+ SSLStatus last_ssl_state_;
+ DISALLOW_COPY_AND_ASSIGN(TestWebContentsDelegate);
+};
+
+class SSLManagerTest : public RenderViewHostTestHarness {
+ public:
+ SSLManagerTest() : RenderViewHostTestHarness() {}
+ ~SSLManagerTest() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SSLManagerTest);
+};
+
+// Tests that VisibleSecurityStateChanged() is called when a password input
+// is shown on an HTTP page.
+TEST_F(SSLManagerTest, NotifyVisibleSSLStateChangeOnHttpPassword) {
+ TestWebContentsDelegate delegate;
+ web_contents()->SetDelegate(&delegate);
+ SSLManager manager(
+ static_cast<NavigationControllerImpl*>(&web_contents()->GetController()));
+
+ NavigateAndCommit(GURL("http://example.test"));
+ EXPECT_FALSE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+ web_contents()->OnPasswordInputShownOnHttp();
+ EXPECT_TRUE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+}
+
+// Tests that VisibleSecurityStateChanged() is called when a credit card input
+// is shown on an HTTP page.
+TEST_F(SSLManagerTest, NotifyVisibleSSLStateChangeOnHttpCreditCard) {
+ TestWebContentsDelegate delegate;
+ web_contents()->SetDelegate(&delegate);
+ SSLManager manager(
+ static_cast<NavigationControllerImpl*>(&web_contents()->GetController()));
+
+ NavigateAndCommit(GURL("http://example.test"));
+ EXPECT_FALSE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
+ web_contents()->OnCreditCardInputShownOnHttp();
+ EXPECT_TRUE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
+}
+
+// Tests that VisibleSecurityStateChanged() is called when password and
+// credit card inputs are shown on an HTTP page.
+TEST_F(SSLManagerTest, NotifyVisibleSSLStateChangeOnPasswordAndHttpCreditCard) {
+ TestWebContentsDelegate delegate;
+ web_contents()->SetDelegate(&delegate);
+ SSLManager manager(
+ static_cast<NavigationControllerImpl*>(&web_contents()->GetController()));
+
+ NavigateAndCommit(GURL("http://example.test"));
+ EXPECT_FALSE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+ EXPECT_FALSE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
+ web_contents()->OnPasswordInputShownOnHttp();
+ web_contents()->OnCreditCardInputShownOnHttp();
+ EXPECT_TRUE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+ EXPECT_TRUE(delegate.last_ssl_state().content_status &
+ SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index f930009229a..bc9409eb5f1 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -193,7 +193,7 @@ void ClearLocalStorageOnUIThread(
origin_matcher.Run(storage_origin,
special_storage_policy.get());
if (can_delete)
- dom_storage_context->DeleteLocalStorage(storage_origin);
+ dom_storage_context->DeleteLocalStorageForPhysicalOrigin(storage_origin);
callback.Run();
return;
@@ -374,6 +374,7 @@ StoragePartitionImpl::StoragePartitionImpl(
HostZoomLevelContext* host_zoom_level_context,
PlatformNotificationContextImpl* platform_notification_context,
BackgroundSyncContext* background_sync_context,
+ PaymentAppContext* payment_app_context,
scoped_refptr<BroadcastChannelProvider> broadcast_channel_provider)
: partition_path_(partition_path),
quota_manager_(quota_manager),
@@ -388,6 +389,7 @@ StoragePartitionImpl::StoragePartitionImpl(
host_zoom_level_context_(host_zoom_level_context),
platform_notification_context_(platform_notification_context),
background_sync_context_(background_sync_context),
+ payment_app_context_(payment_app_context),
broadcast_channel_provider_(std::move(broadcast_channel_provider)),
browser_context_(browser_context) {}
@@ -420,6 +422,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
if (GetBackgroundSyncContext())
GetBackgroundSyncContext()->Shutdown();
+
+ if (GetPaymentAppContext())
+ GetPaymentAppContext()->Shutdown();
}
std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
@@ -509,6 +514,10 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
new BackgroundSyncContext();
background_sync_context->Init(service_worker_context);
+ scoped_refptr<PaymentAppContext> payment_app_context =
+ new PaymentAppContext();
+ payment_app_context->Init(service_worker_context);
+
scoped_refptr<BroadcastChannelProvider>
broadcast_channel_provider = new BroadcastChannelProvider();
@@ -520,6 +529,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
cache_storage_context.get(), service_worker_context.get(),
special_storage_policy.get(), host_zoom_level_context.get(),
platform_notification_context.get(), background_sync_context.get(),
+ payment_app_context.get(),
std::move(broadcast_channel_provider)));
service_worker_context->set_storage_partition(storage_partition.get());
@@ -595,6 +605,10 @@ BackgroundSyncContext* StoragePartitionImpl::GetBackgroundSyncContext() {
return background_sync_context_.get();
}
+PaymentAppContext* StoragePartitionImpl::GetPaymentAppContext() {
+ return payment_app_context_.get();
+}
+
BroadcastChannelProvider* StoragePartitionImpl::GetBroadcastChannelProvider() {
return broadcast_channel_provider_.get();
}
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 584f2dbad86..34dcfa60a89 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -22,6 +22,7 @@
#include "content/browser/host_zoom_level_context.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/browser/payments/payment_app_context.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/content_export.h"
#include "content/common/storage_partition_service.mojom.h"
@@ -74,6 +75,7 @@ class CONTENT_EXPORT StoragePartitionImpl
PlatformNotificationContextImpl* GetPlatformNotificationContext() override;
BackgroundSyncContext* GetBackgroundSyncContext();
+ PaymentAppContext* GetPaymentAppContext();
BroadcastChannelProvider* GetBroadcastChannelProvider();
// mojom::StoragePartitionService interface.
@@ -177,6 +179,7 @@ class CONTENT_EXPORT StoragePartitionImpl
HostZoomLevelContext* host_zoom_level_context,
PlatformNotificationContextImpl* platform_notification_context,
BackgroundSyncContext* background_sync_context,
+ PaymentAppContext* payment_app_context,
scoped_refptr<BroadcastChannelProvider>broadcast_channel_provider);
// We will never have both remove_origin be populated and a cookie_matcher.
@@ -222,6 +225,7 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<HostZoomLevelContext> host_zoom_level_context_;
scoped_refptr<PlatformNotificationContextImpl> platform_notification_context_;
scoped_refptr<BackgroundSyncContext> background_sync_context_;
+ scoped_refptr<PaymentAppContext> payment_app_context_;
scoped_refptr<BroadcastChannelProvider> broadcast_channel_provider_;
mojo::BindingSet<mojom::StoragePartitionService> bindings_;
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index 26ec5d43226..dc3ee844829 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -601,6 +601,9 @@ class StoragePartitionShaderClearTest : public testing::Test {
StoragePartitionShaderClearTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
browser_context_(new TestBrowserContext()) {
+ ShaderCacheFactory::InitInstance(
+ base::ThreadTaskRunnerHandle::Get(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
ShaderCacheFactory::GetInstance()->SetCacheInfo(
kDefaultClientId,
BrowserContext::GetDefaultStoragePartition(
diff --git a/chromium/content/browser/theme_helper_mac.mm b/chromium/content/browser/theme_helper_mac.mm
index 8499fd4271a..eb1dff4868d 100644
--- a/chromium/content/browser/theme_helper_mac.mm
+++ b/chromium/content/browser/theme_helper_mac.mm
@@ -10,6 +10,7 @@
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/common/renderer.mojom.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
@@ -36,7 +37,8 @@ blink::WebScrollbarButtonsPlacement GetButtonPlacement() {
return blink::WebScrollbarButtonsPlacementDoubleEnd;
}
-void FillScrollbarThemeParams(ViewMsg_UpdateScrollbarTheme_Params* params) {
+void FillScrollbarThemeParams(
+ content::mojom::UpdateScrollbarThemeParams* params) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
@@ -53,13 +55,13 @@ void FillScrollbarThemeParams(ViewMsg_UpdateScrollbarTheme_Params* params) {
params->button_placement = GetButtonPlacement();
}
-ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
+void SendSystemColorsChangedMessage(content::mojom::Renderer* renderer) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults synchronize];
- return new ViewMsg_SystemColorsChanged(
+ renderer->OnSystemColorsChanged(
[[defaults stringForKey:@"AppleAquaColorVariant"] intValue],
base::SysNSStringToUTF8(
[defaults stringForKey:@"AppleHighlightedTextColor"]),
@@ -139,22 +141,23 @@ ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd();
it.Advance()) {
- it.GetCurrentValue()->Send(CreateSystemColorsChangedMessage());
+ SendSystemColorsChangedMessage(
+ it.GetCurrentValue()->GetRendererInterface());
}
}
+ (void)notifyPrefsChangedWithRedraw:(BOOL)redraw {
- ViewMsg_UpdateScrollbarTheme_Params params;
- FillScrollbarThemeParams(&params);
- params.redraw = redraw;
-
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd();
it.Advance()) {
+ content::mojom::UpdateScrollbarThemeParamsPtr params =
+ content::mojom::UpdateScrollbarThemeParams::New();
+ FillScrollbarThemeParams(params.get());
+ params->redraw = redraw;
RenderProcessHostImpl* rphi =
static_cast<RenderProcessHostImpl*>(it.GetCurrentValue());
rphi->RecomputeAndUpdateWebKitPreferences();
- rphi->Send(new ViewMsg_UpdateScrollbarTheme(params));
+ rphi->GetRendererInterface()->UpdateScrollbarTheme(std::move(params));
}
}
@@ -190,15 +193,18 @@ void ThemeHelperMac::Observe(int type,
// When a new RenderProcess is created, send it the initial preference
// parameters.
- ViewMsg_UpdateScrollbarTheme_Params params;
- FillScrollbarThemeParams(&params);
- params.redraw = false;
+ content::mojom::UpdateScrollbarThemeParamsPtr params =
+ content::mojom::UpdateScrollbarThemeParams::New();
+ FillScrollbarThemeParams(params.get());
+ params->redraw = false;
RenderProcessHostImpl* rphi =
Source<content::RenderProcessHostImpl>(source).ptr();
rphi->RecomputeAndUpdateWebKitPreferences();
- rphi->Send(new ViewMsg_UpdateScrollbarTheme(params));
- rphi->Send(CreateSystemColorsChangedMessage());
+
+ content::mojom::Renderer* renderer = rphi->GetRendererInterface();
+ renderer->UpdateScrollbarTheme(std::move(params));
+ SendSystemColorsChangedMessage(renderer);
}
} // namespace content
diff --git a/chromium/content/browser/top_document_isolation_browsertest.cc b/chromium/content/browser/top_document_isolation_browsertest.cc
index b0409db8406..6cd1f03dc60 100644
--- a/chromium/content/browser/top_document_isolation_browsertest.cc
+++ b/chromium/content/browser/top_document_isolation_browsertest.cc
@@ -11,10 +11,10 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
-#include "content/test/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "url/gurl.h"
@@ -36,8 +36,8 @@ class TopDocumentIsolationTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
}
FrameTreeNode* root() {
@@ -278,9 +278,8 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
}
-// Flaky. See http://crbug.com/611300.
IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- DISABLED_NavigateToSubframeSiteWithPopup2) {
+ NavigateToSubframeSiteWithPopup2) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
@@ -342,7 +341,11 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
GURL cab_url(embedded_test_server()->GetURL(
"c.com", "/cross_site_iframe_factory.html?c(a, b)"));
- NavigateToURL(shell(), cab_url);
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ NavigateToURL(shell(), cab_url);
+ deleted_observer.WaitUntilDeleted();
+ }
// This c.com navigation currently breaks out of the default subframe process,
// even though that process houses a c.com pop-up.
@@ -365,13 +368,22 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
// If we navigate the popup to a new site, it ought to transfer processes.
GURL d_url(embedded_test_server()->GetURL(
"d.com", "/cross_site_iframe_factory.html?d"));
- NavigateToURL(popup, d_url);
+ {
+ RenderFrameDeletedObserver deleted_observer(
+ popup_root->current_frame_host());
+ NavigateToURL(popup, d_url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site D ------------ proxies for B\n"
"Where B = default subframe process\n"
" D = http://d.com/",
DepictFrameTree(popup_root));
- NavigateToURL(shell(), d_url);
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ NavigateToURL(shell(), d_url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site D\n"
"Where D = http://d.com/",
@@ -382,15 +394,7 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
}
-// Flaky on Mac. See https://crbug.com/611344.
-#if defined(OS_MACOSX)
-#define MAYBE_FramesForSitesInHistory DISABLED_FramesForSitesInHistory
-#else
-#define MAYBE_FramesForSitesInHistory FramesForSitesInHistory
-#endif
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- MAYBE_FramesForSitesInHistory) {
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
@@ -410,7 +414,14 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
// Browser-initiated navigation to b.com.
- NavigateToURL(shell(), b_url);
+ {
+ // For any cross-process navigations, we must wait for the old RenderFrame
+ // to be deleted before calling DepictFrameTree, or else there's a chance
+ // the old SiteInstance could be listed while pending deletion.
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ NavigateToURL(shell(), b_url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site B\n"
"Where B = http://b.com/",
@@ -424,16 +435,24 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
// Browser-initiated navigation to c.com.
- NavigateToURL(shell(), c_url);
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ NavigateToURL(shell(), c_url);
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site C\n"
"Where C = http://c.com/",
DepictFrameTree(root()));
// Now, navigate to a fourth site with iframes to the sites in the history.
- NavigateToURL(shell(),
- embedded_test_server()->GetURL(
- "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site D ------------ proxies for E\n"
@@ -445,12 +464,20 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
// Now try going back.
- GoBack();
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ GoBack();
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site C\n"
"Where C = http://c.com/",
DepictFrameTree(root()));
- GoBack();
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ GoBack();
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site B\n"
"Where B = http://b.com/",
@@ -460,7 +487,11 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
" Site B\n"
"Where B = http://b.com/",
DepictFrameTree(root()));
- GoBack();
+ {
+ RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
+ GoBack();
+ deleted_observer.WaitUntilDeleted();
+ }
EXPECT_EQ(
" Site A\n"
"Where A = http://a.com/",
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index 8628a683d40..a6947f86c26 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -19,7 +19,6 @@
namespace content {
class BackgroundTracingRule;
-class TraceMessageFilter;
class TracingDelegate;
class BackgroundTracingManagerImpl : public BackgroundTracingManager {
diff --git a/chromium/content/browser/tracing/memory_tracing_browsertest.cc b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
index 80ccfae3df2..c015532545d 100644
--- a/chromium/content/browser/tracing/memory_tracing_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
@@ -13,6 +13,7 @@
#include "base/trace_event/memory_dump_provider.h"
#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 "content/public/browser/tracing_controller.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -109,6 +110,12 @@ class MemoryTracingTest : public ContentBrowserTest {
}
void EnableMemoryTracing() {
+ // Re-enabling tracing could crash these tests https://crbug.com/657628 .
+ if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) {
+ FAIL() << "Tracing seems to be already enabled. "
+ "Very likely this is because the startup tracing file "
+ "has been leaked from a previous test.";
+ }
// Enable tracing without periodic dumps.
base::trace_event::TraceConfig trace_config(
base::trace_event::TraceConfigMemoryTestUtil::
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
index e46341a0c74..b4887fc1c4e 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ b/chromium/content/browser/tracing/power_tracing_agent.cc
@@ -181,4 +181,9 @@ bool PowerTracingAgent::SupportsExplicitClockSync() {
return battor_agent_->SupportsExplicitClockSync();
}
+void PowerTracingAgent::OnGetFirmwareGitHashComplete(
+ const std::string& version, battor::BattOrError error) {
+ return;
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/power_tracing_agent.h b/chromium/content/browser/tracing/power_tracing_agent.h
index ae5079e4cc2..3d82fa070fa 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.h
+++ b/chromium/content/browser/tracing/power_tracing_agent.h
@@ -46,6 +46,8 @@ class PowerTracingAgent : public base::trace_event::TracingAgent,
void OnStopTracingComplete(const std::string& trace,
battor::BattOrError error) override;
void OnRecordClockSyncMarkerComplete(battor::BattOrError error) override;
+ void OnGetFirmwareGitHashComplete(const std::string& version,
+ battor::BattOrError error) override;
private:
// This allows constructor and destructor to be private and usable only
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index 4062970c276..70089d96101 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -44,8 +44,6 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(TracingHostMsg_EndTracingAck, OnEndTracingAck)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceDataCollected,
OnTraceDataCollected)
- IPC_MESSAGE_HANDLER(TracingHostMsg_WatchEventMatched,
- OnWatchEventMatched)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceLogStatusReply,
OnTraceLogStatusReply)
IPC_MESSAGE_HANDLER(TracingHostMsg_GlobalMemoryDumpRequest,
@@ -89,15 +87,6 @@ void TraceMessageFilter::SendGetTraceLogStatus() {
Send(new TracingMsg_GetTraceLogStatus);
}
-void TraceMessageFilter::SendSetWatchEvent(const std::string& category_name,
- const std::string& event_name) {
- Send(new TracingMsg_SetWatchEvent(category_name, event_name));
-}
-
-void TraceMessageFilter::SendCancelWatchEvent() {
- Send(new TracingMsg_CancelWatchEvent);
-}
-
// Called by TracingControllerImpl, which handles the multiprocess coordination.
void TraceMessageFilter::SendProcessMemoryDumpRequest(
const base::trace_event::MemoryDumpRequestArgs& args) {
@@ -134,10 +123,6 @@ void TraceMessageFilter::OnTraceDataCollected(const std::string& data) {
TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr);
}
-void TraceMessageFilter::OnWatchEventMatched() {
- TracingControllerImpl::GetInstance()->OnWatchEventMatched();
-}
-
void TraceMessageFilter::OnTraceLogStatusReply(
const base::trace_event::TraceLogStatus& status) {
if (is_awaiting_buffer_percent_full_ack_) {
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 2ca4738857a..68f011fa36a 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -460,46 +460,6 @@ bool TracingControllerImpl::GetTraceBufferUsage(
return true;
}
-bool TracingControllerImpl::SetWatchEvent(
- const std::string& category_name,
- const std::string& event_name,
- const WatchEventCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (callback.is_null())
- return false;
-
- watch_category_name_ = category_name;
- watch_event_name_ = event_name;
- watch_event_callback_ = callback;
-
- TraceLog::GetInstance()->SetWatchEvent(
- category_name, event_name,
- base::Bind(&TracingControllerImpl::OnWatchEventMatched,
- base::Unretained(this)));
-
- for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
- it != trace_message_filters_.end(); ++it) {
- it->get()->SendSetWatchEvent(category_name, event_name);
- }
- return true;
-}
-
-bool TracingControllerImpl::CancelWatchEvent() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!can_cancel_watch_event())
- return false;
-
- for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
- it != trace_message_filters_.end(); ++it) {
- it->get()->SendCancelWatchEvent();
- }
-
- watch_event_callback_.Reset();
- return true;
-}
-
bool TracingControllerImpl::IsTracing() const {
return is_tracing_;
}
@@ -523,17 +483,13 @@ void TracingControllerImpl::AddTraceMessageFilter(
#endif
trace_message_filters_.insert(trace_message_filter);
- if (can_cancel_watch_event()) {
- trace_message_filter->SendSetWatchEvent(watch_category_name_,
- watch_event_name_);
- }
if (can_stop_tracing()) {
trace_message_filter->SendBeginTracing(
TraceLog::GetInstance()->GetCurrentTraceConfig());
}
- FOR_EACH_OBSERVER(TraceMessageFilterObserver, trace_message_filter_observers_,
- OnTraceMessageFilterAdded(trace_message_filter));
+ for (auto& observer : trace_message_filter_observers_)
+ observer.OnTraceMessageFilterAdded(trace_message_filter);
}
void TracingControllerImpl::RemoveTraceMessageFilter(
@@ -789,18 +745,6 @@ void TracingControllerImpl::OnTraceLogStatusReply(
}
}
-void TracingControllerImpl::OnWatchEventMatched() {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnWatchEventMatched,
- base::Unretained(this)));
- return;
- }
-
- if (!watch_event_callback_.is_null())
- watch_event_callback_.Run();
-}
-
void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
tracing_uis_.insert(tracing_ui);
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 44b4c8f6100..0c7b8ea7cae 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -22,7 +22,6 @@
namespace base {
class RefCountedString;
-class RefCountedMemory;
}
namespace content {
@@ -73,10 +72,6 @@ class TracingControllerImpl
const GetTraceBufferUsageCallback& callback) override;
void AddMetadata(const base::DictionaryValue& metadata) override;
- bool SetWatchEvent(const std::string& category_name,
- const std::string& event_name,
- const WatchEventCallback& callback) override;
- bool CancelWatchEvent() override;
bool IsTracing() const override;
void RegisterTracingUI(TracingUI* tracing_ui);
@@ -144,10 +139,6 @@ class TracingControllerImpl
return pending_trace_buffer_usage_callback_.is_null();
}
- bool can_cancel_watch_event() const {
- return !watch_event_callback_.is_null();
- }
-
void PerformNextQueuedGlobalMemoryDump();
// Methods for use by TraceMessageFilter.
@@ -188,8 +179,6 @@ class TracingControllerImpl
void FinalizeGlobalMemoryDumpIfAllProcessesReplied();
- void OnWatchEventMatched();
-
void SetEnabledOnFileThread(
const base::trace_event::TraceConfig& trace_config,
int mode,
@@ -245,10 +234,6 @@ class TracingControllerImpl
GetCategoriesDoneCallback pending_get_categories_done_callback_;
GetTraceBufferUsageCallback pending_trace_buffer_usage_callback_;
- std::string watch_category_name_;
- std::string watch_event_name_;
- WatchEventCallback watch_event_callback_;
-
base::ObserverList<TraceMessageFilterObserver>
trace_message_filter_observers_;
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 3e32838f33c..eec9742fbbc 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -94,11 +94,6 @@ bool GetTracingOptions(const std::string& data64,
if (enable_systrace)
trace_config->EnableSystrace();
- bool enable_sampling;
- options_ok &= options->GetBoolean("useSampling", &enable_sampling);
- if (enable_sampling)
- trace_config->EnableSampling();
-
if (!options_ok) {
LOG(ERROR) << "Malformed options";
return false;
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index 708a09d2f1f..70bb8c0c5bc 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -37,10 +37,10 @@
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
-#include "content/public/common/service_names.h"
+#include "content/public/common/service_names.mojom.h"
#include "mojo/edk/embedder/embedder.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/connection.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
@@ -67,17 +67,16 @@ class UtilitySandboxedProcessLauncherDelegate
UtilitySandboxedProcessLauncherDelegate(const base::FilePath& exposed_dir,
bool launch_elevated,
bool no_sandbox,
- const base::EnvironmentMap& env,
- ChildProcessHost* host)
+ const base::EnvironmentMap& env)
: exposed_dir_(exposed_dir),
#if defined(OS_WIN)
launch_elevated_(launch_elevated)
#elif defined(OS_POSIX)
- env_(env),
+ env_(env)
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
- no_sandbox_(no_sandbox),
+ ,
+ no_sandbox_(no_sandbox)
#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
- ipc_fd_(host->TakeClientFileDescriptor())
#endif // OS_WIN
{}
@@ -114,7 +113,6 @@ class UtilitySandboxedProcessLauncherDelegate
}
#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
base::EnvironmentMap GetEnvironment() override { return env_; }
- base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
SandboxType GetSandboxType() override {
@@ -131,7 +129,6 @@ class UtilitySandboxedProcessLauncherDelegate
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
bool no_sandbox_;
#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
- base::ScopedFD ipc_fd_;
#endif // OS_WIN
};
@@ -165,7 +162,7 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
name_(base::ASCIIToUTF16("utility process")),
weak_ptr_factory_(this) {
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_UTILITY, this, kUtilityServiceName));
+ PROCESS_TYPE_UTILITY, this, mojom::kUtilityServiceName));
}
UtilityProcessHostImpl::~UtilityProcessHostImpl() {
@@ -229,7 +226,8 @@ bool UtilityProcessHostImpl::Start() {
return StartProcess();
}
-shell::InterfaceProvider* UtilityProcessHostImpl::GetRemoteInterfaces() {
+service_manager::InterfaceProvider*
+UtilityProcessHostImpl::GetRemoteInterfaces() {
return process_->child_connection()->GetRemoteInterfaces();
}
@@ -262,8 +260,7 @@ bool UtilityProcessHostImpl::StartProcess() {
// support single process mode this way.
in_process_thread_.reset(
g_utility_main_thread_factory(InProcessChildThreadParams(
- BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
- ->task_runner(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
process_->child_connection()->service_token())));
in_process_thread_->Start();
} else {
@@ -340,13 +337,9 @@ bool UtilityProcessHostImpl::StartProcess() {
cmd_line->AppendSwitch(switches::kUtilityProcessRunningElevated);
#endif
- process_->Launch(
- new UtilitySandboxedProcessLauncherDelegate(exposed_dir_,
- run_elevated_,
- no_sandbox_, env_,
- process_->GetHost()),
- cmd_line,
- true);
+ process_->Launch(new UtilitySandboxedProcessLauncherDelegate(
+ exposed_dir_, run_elevated_, no_sandbox_, env_),
+ cmd_line, true);
}
return true;
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 7e915f53a75..55fa31d82c9 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -57,7 +57,7 @@ class CONTENT_EXPORT UtilityProcessHostImpl
void SetEnv(const base::EnvironmentMap& env) override;
#endif
bool Start() override;
- shell::InterfaceProvider* GetRemoteInterfaces() override;
+ service_manager::InterfaceProvider* GetRemoteInterfaces() override;
void SetName(const base::string16& name) override;
void set_child_flags(int flags) { child_flags_ = flags; }
diff --git a/chromium/content/browser/utility_process_host_impl_browsertest.cc b/chromium/content/browser/utility_process_host_impl_browsertest.cc
index 38e81a87391..c1f956eead1 100644
--- a/chromium/content/browser/utility_process_host_impl_browsertest.cc
+++ b/chromium/content/browser/utility_process_host_impl_browsertest.cc
@@ -11,8 +11,8 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_service.mojom.h"
-#include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
namespace content {
diff --git a/chromium/content/browser/vibration_browsertest.cc b/chromium/content/browser/vibration_browsertest.cc
index 320e1294351..2f3a83ab3f7 100644
--- a/chromium/content/browser/vibration_browsertest.cc
+++ b/chromium/content/browser/vibration_browsertest.cc
@@ -18,7 +18,7 @@
#include "content/shell/browser/shell.h"
#include "device/vibration/vibration_manager.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
// These tests run against a dummy implementation of the VibrationManager
// service. That is, they verify that the service implementation is correctly
diff --git a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
index 59e3ab71e1c..c86ad7bc5f9 100644
--- a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -4,7 +4,6 @@
#include "base/command_line.h"
#include "base/test/test_timeouts.h"
-#include "content/browser/wake_lock/wake_lock_service_context.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -13,6 +12,7 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "device/wake_lock/wake_lock_service_context.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -62,7 +62,7 @@ class WakeLockTest : public ContentBrowserTest {
return GetNestedFrameNode()->current_frame_host();
}
- WakeLockServiceContext* GetWakeLockServiceContext() {
+ device::WakeLockServiceContext* GetWakeLockServiceContext() {
return GetWebContentsImpl()->GetWakeLockServiceContext();
}
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.cc b/chromium/content/browser/wake_lock/wake_lock_service_context.cc
deleted file mode 100644
index 7603595259a..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/wake_lock/wake_lock_service_context.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "device/power_save_blocker/power_save_blocker.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-WakeLockServiceContext::WakeLockServiceContext(
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
- base::Callback<gfx::NativeView()> native_view_getter)
- : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- file_task_runner_(file_task_runner),
- num_lock_requests_(0),
- native_view_getter_(native_view_getter),
- weak_factory_(this) {}
-
-WakeLockServiceContext::~WakeLockServiceContext() {}
-
-void WakeLockServiceContext::CreateService(
- mojo::InterfaceRequest<blink::mojom::WakeLockService> request) {
- mojo::MakeStrongBinding(
- base::MakeUnique<WakeLockServiceImpl>(weak_factory_.GetWeakPtr()),
- std::move(request));
-}
-
-void WakeLockServiceContext::RequestWakeLock() {
- DCHECK(main_task_runner_->RunsTasksOnCurrentThread());
- num_lock_requests_++;
- UpdateWakeLock();
-}
-
-void WakeLockServiceContext::CancelWakeLock() {
- DCHECK(main_task_runner_->RunsTasksOnCurrentThread());
- num_lock_requests_--;
- UpdateWakeLock();
-}
-
-bool WakeLockServiceContext::HasWakeLockForTests() const {
- return !!wake_lock_;
-}
-
-void WakeLockServiceContext::CreateWakeLock() {
- DCHECK(!wake_lock_);
- wake_lock_.reset(new device::PowerSaveBlocker(
- device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- device::PowerSaveBlocker::kReasonOther, "Wake Lock API",
- main_task_runner_, file_task_runner_));
-
-#if defined(OS_ANDROID)
- gfx::NativeView native_view = native_view_getter_.Run();
- if (native_view) {
- wake_lock_.get()->InitDisplaySleepBlocker(native_view);
- }
-#endif
-}
-
-void WakeLockServiceContext::RemoveWakeLock() {
- DCHECK(wake_lock_);
- wake_lock_.reset();
-}
-
-void WakeLockServiceContext::UpdateWakeLock() {
- DCHECK(num_lock_requests_ >= 0);
- if (num_lock_requests_) {
- if (!wake_lock_)
- CreateWakeLock();
- } else {
- if (wake_lock_)
- RemoveWakeLock();
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.h b/chromium/content/browser/wake_lock/wake_lock_service_context.h
deleted file mode 100644
index 1ee85fe0b37..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_CONTEXT_H_
-#define CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_CONTEXT_H_
-
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "content/browser/wake_lock/wake_lock_service_impl.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace device {
-class PowerSaveBlocker;
-} // namespace device
-
-namespace content {
-
-class CONTENT_EXPORT WakeLockServiceContext {
- public:
- WakeLockServiceContext(
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
- base::Callback<gfx::NativeView()> native_view_getter);
- ~WakeLockServiceContext();
-
- // Creates a WakeLockServiceImpl that is strongly bound to |request|.
- void CreateService(
- mojo::InterfaceRequest<blink::mojom::WakeLockService> request);
-
- // Requests wake lock.
- void RequestWakeLock();
-
- // Cancels pending wake lock request.
- void CancelWakeLock();
-
- // Used by tests.
- bool HasWakeLockForTests() const;
-
- private:
- void CreateWakeLock();
- void RemoveWakeLock();
- void UpdateWakeLock();
-
- scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
-
- int num_lock_requests_;
-
- // The actual power save blocker for screen.
- std::unique_ptr<device::PowerSaveBlocker> wake_lock_;
- base::Callback<gfx::NativeView()> native_view_getter_;
-
- base::WeakPtrFactory<WakeLockServiceContext> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(WakeLockServiceContext);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_CONTEXT_H_
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context_unittest.cc b/chromium/content/browser/wake_lock/wake_lock_service_context_unittest.cc
deleted file mode 100644
index 6240132303a..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_service_context_unittest.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/wake_lock/wake_lock_service_context.h"
-
-#include <memory>
-
-#include "base/message_loop/message_loop.h"
-#include "base/process/kill.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class WakeLockServiceContextTest : public testing::Test {
- public:
- WakeLockServiceContextTest()
- : wake_lock_service_context_(
- base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&WakeLockServiceContextTest::GetNativeView,
- base::Unretained(this))) {}
-
- protected:
- void RequestWakeLock() { GetWakeLockServiceContext()->RequestWakeLock(); }
-
- void CancelWakeLock() { GetWakeLockServiceContext()->CancelWakeLock(); }
-
- WakeLockServiceContext* GetWakeLockServiceContext() {
- return &wake_lock_service_context_;
- }
-
- bool HasWakeLock() {
- return GetWakeLockServiceContext()->HasWakeLockForTests();
- }
-
- private:
- gfx::NativeView GetNativeView() { return nullptr; }
-
- base::MessageLoop message_loop_;
- WakeLockServiceContext wake_lock_service_context_;
-};
-
-TEST_F(WakeLockServiceContextTest, NoLockInitially) {
- EXPECT_FALSE(HasWakeLock());
-}
-
-TEST_F(WakeLockServiceContextTest, LockUnlock) {
- ASSERT_TRUE(GetWakeLockServiceContext());
-
- // Request wake lock.
- RequestWakeLock();
-
- // Should set the blocker.
- EXPECT_TRUE(HasWakeLock());
-
- // Remove wake lock request.
- CancelWakeLock();
-
- // Should remove the blocker.
- EXPECT_FALSE(HasWakeLock());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_impl.cc b/chromium/content/browser/wake_lock/wake_lock_service_impl.cc
deleted file mode 100644
index 6e0d159f631..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_service_impl.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/wake_lock/wake_lock_service_impl.h"
-
-#include <utility>
-
-#include "content/browser/wake_lock/wake_lock_service_context.h"
-
-namespace content {
-
-WakeLockServiceImpl::WakeLockServiceImpl(
- base::WeakPtr<WakeLockServiceContext> context)
- : context_(context), wake_lock_request_outstanding_(false) {}
-
-WakeLockServiceImpl::~WakeLockServiceImpl() {
- CancelWakeLock();
-}
-
-void WakeLockServiceImpl::RequestWakeLock() {
- if (!context_ || wake_lock_request_outstanding_)
- return;
-
- wake_lock_request_outstanding_ = true;
- context_->RequestWakeLock();
-}
-
-void WakeLockServiceImpl::CancelWakeLock() {
- if (!context_ || !wake_lock_request_outstanding_)
- return;
-
- wake_lock_request_outstanding_ = false;
- context_->CancelWakeLock();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_impl.h b/chromium/content/browser/wake_lock/wake_lock_service_impl.h
deleted file mode 100644
index 495e2c04a4c..00000000000
--- a/chromium/content/browser/wake_lock/wake_lock_service_impl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_
-#define CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "third_party/WebKit/public/platform/modules/wake_lock/wake_lock_service.mojom.h"
-
-namespace content {
-
-class WakeLockServiceContext;
-
-class WakeLockServiceImpl : public blink::mojom::WakeLockService {
- public:
- explicit WakeLockServiceImpl(base::WeakPtr<WakeLockServiceContext> context);
- ~WakeLockServiceImpl() override;
-
- // WakeLockSevice implementation.
- void RequestWakeLock() override;
- void CancelWakeLock() override;
-
- private:
- base::WeakPtr<WakeLockServiceContext> context_;
- bool wake_lock_request_outstanding_;
-
- DISALLOW_COPY_AND_ASSIGN(WakeLockServiceImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_
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 4ff4abe5dd2..b826800c0df 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -110,10 +110,6 @@ class ArrowLayerDelegate : public ui::LayerDelegate {
void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
- base::Closure PrepareForLayerBoundsChange() override {
- return base::Closure();
- }
-
const gfx::Image& image_;
const bool left_arrow_;
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 7ee72bd4a23..a3ea6c0eb2d 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
@@ -13,11 +13,8 @@
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/image/image.h"
-struct ViewHostMsg_UpdateRect_Params;
-
namespace content {
-class OverscrollWindowDelegate;
class OverscrollNavigationOverlayTest;
// When a history navigation is triggered at the end of an overscroll
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 29fee88c738..bf9af22e4f2 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
@@ -296,7 +296,7 @@ TEST_F(OverscrollNavigationOverlayTest, CancelAfterSuccessfulNavigation) {
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
NavigationEntry* pending = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
+ pending->GetUniqueID(), false, pending->GetURL());
EXPECT_EQ(contents()->GetURL(), third());
}
@@ -312,7 +312,7 @@ TEST_F(OverscrollNavigationOverlayTest, Navigation_PaintUpdate) {
NavigationEntry* pending = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
+ pending->GetUniqueID(), false, pending->GetURL());
ReceivePaintUpdate();
// Navigation was committed and the paint update was received - we should no
@@ -335,7 +335,7 @@ TEST_F(OverscrollNavigationOverlayTest, Navigation_LoadingUpdate) {
EXPECT_FALSE(GetOverlay()->web_contents());
NavigationEntry* pending = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
- pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
+ pending->GetUniqueID(), false, pending->GetURL());
EXPECT_EQ(contents()->GetURL(), third());
}
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 878197803c4..f19e5f8bcc7 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_animation.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_animation.h
@@ -18,13 +18,11 @@ class Window;
namespace ui {
class Layer;
-class LayerAnimator;
}
namespace content {
class ShadowLayerDelegate;
-class WebContentsImpl;
// Manages the animation of a window sliding on top or behind another one. The
// main window, which is the one displayed before the animation starts, is not
diff --git a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
index a4a1660be5b..89ffa649f10 100644
--- a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -4,7 +4,6 @@
#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
-#include "base/bind.h"
#include "base/macros.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/aura/window.h"
@@ -59,8 +58,4 @@ void ShadowLayerDelegate::OnDelegatedFrameDamage(
void ShadowLayerDelegate::OnDeviceScaleFactorChanged(float scale_factor) {
}
-base::Closure ShadowLayerDelegate::PrepareForLayerBoundsChange() {
- return base::Bind(&base::DoNothing);
-}
-
} // namespace content
diff --git a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
index 6c1729f3e53..5d358a05f9a 100644
--- a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
+++ b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
@@ -11,10 +11,6 @@
#include "base/macros.h"
#include "ui/compositor/layer_delegate.h"
-namespace aura {
-class Window;
-}
-
namespace ui {
class Layer;
}
@@ -37,7 +33,6 @@ class ShadowLayerDelegate : public 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;
- base::Closure PrepareForLayerBoundsChange() override;
std::unique_ptr<ui::Layer> layer_;
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index d85822d6c47..9be39aeb0fd 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -27,6 +27,7 @@
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/android/app_web_message_port_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/message_port_provider.h"
@@ -105,8 +106,15 @@ ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(
if (node->HasFloatAttribute(ui::AX_ATTR_FONT_SIZE)) {
color = node->GetIntAttribute(ui::AX_ATTR_COLOR);
bgcolor = node->GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR);
- size = node->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE);
text_style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
+
+ // The font size is just the computed style for that element; apply
+ // transformations to get the actual pixel size.
+ gfx::RectF text_size_rect(
+ 0, 0, 1, node->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE));
+ gfx::Rect scaled_text_size_rect = node->RelativeToAbsoluteBounds(
+ text_size_rect, false);
+ size = scaled_text_size_rect.height();
}
const gfx::Rect& absolute_rect = node->GetPageBoundsRect();
@@ -239,7 +247,6 @@ bool WebContentsAndroid::Register(JNIEnv* env) {
WebContentsAndroid::WebContentsAndroid(WebContentsImpl* web_contents)
: web_contents_(web_contents),
navigation_controller_(&(web_contents->GetController())),
- synchronous_compositor_client_(nullptr),
weak_factory_(this) {
g_allocated_web_contents_androids.Get().insert(this);
JNIEnv* env = AttachCurrentThread();
@@ -428,7 +435,7 @@ void WebContentsAndroid::ExitFullscreen(JNIEnv* env,
web_contents_->ExitFullscreen(/*will_cause_resize=*/false);
}
-void WebContentsAndroid::UpdateTopControlsState(
+void WebContentsAndroid::UpdateBrowserControlsState(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
bool enable_hiding,
@@ -437,18 +444,8 @@ void WebContentsAndroid::UpdateTopControlsState(
RenderViewHost* host = web_contents_->GetRenderViewHost();
if (!host)
return;
- host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
- enable_hiding,
- enable_showing,
- animate));
-}
-
-void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- if (!host)
- return;
- host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
+ host->Send(new ViewMsg_UpdateBrowserControlsState(
+ host->GetRoutingID(), enable_hiding, enable_showing, animate));
}
void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
@@ -559,18 +556,30 @@ void WebContentsAndroid::AddMessageToDevToolsConsole(
ConvertJavaStringToUTF8(env, message));
}
-void WebContentsAndroid::SendMessageToFrame(
+void WebContentsAndroid::PostMessageToFrame(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
- const JavaParamRef<jstring>& frame_name,
- const JavaParamRef<jstring>& message,
- const JavaParamRef<jstring>& target_origin) {
+ const JavaParamRef<jstring>& jframe_name,
+ const JavaParamRef<jstring>& jmessage,
+ const JavaParamRef<jstring>& jtarget_origin,
+ const JavaParamRef<jintArray>& jsent_ports) {
base::string16 source_origin;
- base::string16 j_target_origin(ConvertJavaStringToUTF16(env, target_origin));
- base::string16 j_message(ConvertJavaStringToUTF16(env, message));
+ base::string16 target_origin(ConvertJavaStringToUTF16(env, jtarget_origin));
+ base::string16 message(ConvertJavaStringToUTF16(env, jmessage));
std::vector<int> ports;
+
+ if (!jsent_ports.is_null())
+ base::android::JavaIntArrayToIntVector(env, jsent_ports, &ports);
content::MessagePortProvider::PostMessageToFrame(
- web_contents_, source_origin, j_target_origin, j_message, ports);
+ web_contents_, source_origin, target_origin, message, ports);
+}
+
+void WebContentsAndroid::CreateMessageChannel(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobjectArray>& ports) {
+ content::MessagePortProvider::GetAppWebMessagePortService()
+ ->CreateMessageChannel(env, ports, web_contents_);
}
jboolean WebContentsAndroid::HasAccessedInitialDocument(
@@ -600,21 +609,6 @@ void WebContentsAndroid::RequestAccessibilitySnapshot(
snapshot_callback);
}
-void WebContentsAndroid::ResumeMediaSession(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- web_contents_->ResumeMediaSession();
-}
-
-void WebContentsAndroid::SuspendMediaSession(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- web_contents_->SuspendMediaSession();
-}
-
-void WebContentsAndroid::StopMediaSession(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- web_contents_->StopMediaSession();
-}
-
ScopedJavaLocalRef<jstring> WebContentsAndroid::GetEncoding(
JNIEnv* env,
const JavaParamRef<jobject>& obj) const {
@@ -638,7 +632,7 @@ void WebContentsAndroid::GetContentBitmap(
weak_factory_.GetWeakPtr(),
base::Owned(new ScopedJavaGlobalRef<jobject>(env, obj)),
base::Owned(new ScopedJavaGlobalRef<jobject>(env, jcallback)));
- SkColorType pref_color_type = gfx::ConvertToSkiaColorType(color_type.obj());
+ SkColorType pref_color_type = gfx::ConvertToSkiaColorType(color_type);
if (!view || pref_color_type == kUnknown_SkColorType) {
result_callback.Run(SkBitmap(), READBACK_FAILED);
return;
@@ -677,6 +671,14 @@ int WebContentsAndroid::DownloadImage(
env, jcallback))));
}
+void WebContentsAndroid::DismissTextHandles(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+ if (view)
+ view->DismissTextHandles();
+}
+
void WebContentsAndroid::OnFinishGetContentBitmap(
ScopedJavaGlobalRef<jobject>* obj,
ScopedJavaGlobalRef<jobject>* callback,
@@ -720,4 +722,11 @@ void WebContentsAndroid::OnFinishDownloadImage(
Java_WebContentsImpl_onDownloadImageFinished(
env, *obj, *callback, id, http_status_code, jurl, jbitmaps, jsizes);
}
+
+void WebContentsAndroid::SetMediaSession(
+ const ScopedJavaLocalRef<jobject>& j_media_session) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_WebContentsImpl_setMediaSession(env, obj_, j_media_session);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index 5aaaf31b318..d23f93a2048 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -21,7 +21,6 @@
namespace content {
-class SynchronousCompositorClient;
class WebContentsImpl;
// Android wrapper around WebContents that provides safer passage from java and
@@ -100,13 +99,12 @@ class CONTENT_EXPORT WebContentsAndroid
const base::android::JavaParamRef<jobject>& obj);
void ExitFullscreen(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- void UpdateTopControlsState(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- bool enable_hiding,
- bool enable_showing,
- bool animate);
- void ShowImeIfNeeded(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
+ void UpdateBrowserControlsState(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ bool enable_hiding,
+ bool enable_showing,
+ bool animate);
void ScrollFocusedEditableNodeIntoView(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -133,12 +131,18 @@ class CONTENT_EXPORT WebContentsAndroid
jint level,
const base::android::JavaParamRef<jstring>& message);
- void SendMessageToFrame(
+ void PostMessageToFrame(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jstring>& jframe_name,
+ const base::android::JavaParamRef<jstring>& jmessage,
+ const base::android::JavaParamRef<jstring>& jtarget_origin,
+ const base::android::JavaParamRef<jintArray>& jsent_ports);
+
+ void CreateMessageChannel(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jstring>& frame_name,
- const base::android::JavaParamRef<jstring>& message,
- const base::android::JavaParamRef<jstring>& target_origin);
+ const base::android::JavaParamRef<jobjectArray>& ports);
jboolean HasAccessedInitialDocument(
JNIEnv* env,
@@ -152,13 +156,6 @@ class CONTENT_EXPORT WebContentsAndroid
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& callback);
- void ResumeMediaSession(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
- void SuspendMediaSession(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
- void StopMediaSession(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
base::android::ScopedJavaLocalRef<jstring> GetEncoding(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) const;
@@ -177,13 +174,6 @@ class CONTENT_EXPORT WebContentsAndroid
void ReloadLoFiImages(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- void set_synchronous_compositor_client(SynchronousCompositorClient* client) {
- synchronous_compositor_client_ = client;
- }
- SynchronousCompositorClient* synchronous_compositor_client() const {
- return synchronous_compositor_client_;
- }
-
int DownloadImage(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jstring>& url,
@@ -191,6 +181,11 @@ class CONTENT_EXPORT WebContentsAndroid
jint max_bitmap_size,
jboolean bypass_cache,
const base::android::JavaParamRef<jobject>& jcallback);
+ void DismissTextHandles(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+
+ void SetMediaSession(
+ const base::android::ScopedJavaLocalRef<jobject>& j_media_session);
private:
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
@@ -213,7 +208,6 @@ class CONTENT_EXPORT WebContentsAndroid
WebContentsImpl* web_contents_;
NavigationControllerAndroid navigation_controller_;
base::android::ScopedJavaGlobalRef<jobject> obj_;
- SynchronousCompositorClient* synchronous_compositor_client_;
base::WeakPtrFactory<WebContentsAndroid> weak_factory_;
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index ae86bc72695..57405373178 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -37,6 +37,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/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"
#include "content/browser/download/download_stats.h"
@@ -53,13 +54,14 @@
#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/host_zoom_map_impl.h"
+#include "content/browser/host_zoom_map_observer.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"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/web_contents_audio_muter.h"
#include "content/browser/media/media_web_contents_observer.h"
-#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/plugin_content_origin_whitelist.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -71,7 +73,6 @@
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/wake_lock/wake_lock_service_context.h"
#include "content/browser/web_contents/web_contents_view_child_frame.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/browser/webui/generic_handler.h"
@@ -79,6 +80,7 @@
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
+#include "content/common/drag_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/page_messages.h"
@@ -90,9 +92,9 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/guest_mode.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/javascript_dialog_manager.h"
@@ -109,6 +111,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_unresponsive_state.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -121,12 +124,14 @@
#include "content/public/common/web_preferences.h"
#include "device/geolocation/geolocation_service_context.h"
#include "device/nfc/nfc.mojom.h"
+#include "device/wake_lock/wake_lock_service_context.h"
#include "net/base/url_util.h"
#include "net/http/http_cache.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "services/shell/public/cpp/interface_provider.h"
+#include "services/service_manager/public/cpp/interface_provider.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"
#include "ui/accessibility/ax_tree_combiner.h"
@@ -134,6 +139,11 @@
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/gl/gl_switches.h"
+#if defined(OS_WIN)
+#include "content/browser/renderer_host/dip_util.h"
+#include "ui/gfx/geometry/dip_util.h"
+#endif
+
#if defined(OS_ANDROID)
#include "content/browser/android/content_video_view.h"
#include "content/browser/android/date_time_chooser_android.h"
@@ -417,8 +427,6 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
upload_size_(0),
upload_position_(0),
is_resume_pending_(false),
- displayed_insecure_content_(false),
- displayed_content_with_cert_errors_(false),
has_accessed_initial_document_(false),
theme_color_(SK_ColorTRANSPARENT),
last_sent_theme_color_(SK_ColorTRANSPARENT),
@@ -451,6 +459,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
virtual_keyboard_requested_(false),
page_scale_factor_is_one_(true),
mouse_lock_widget_(nullptr),
+ is_overlay_content_(false),
loading_weak_factory_(this),
weak_factory_(this) {
frame_tree_.SetFrameRemoveListener(
@@ -465,9 +474,10 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
pepper_playback_observer_.reset(new PepperPlaybackObserver(this));
#endif
loader_io_thread_notifier_.reset(new LoaderIOThreadNotifier(this));
- wake_lock_service_context_.reset(new WakeLockServiceContext(
+ wake_lock_service_context_.reset(new device::WakeLockServiceContext(
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
base::Bind(&WebContentsImpl::GetNativeView, base::Unretained(this))));
+ host_zoom_map_observer_.reset(new HostZoomMapObserver(this));
}
WebContentsImpl::~WebContentsImpl() {
@@ -479,9 +489,9 @@ WebContentsImpl::~WebContentsImpl() {
entry.second->CloseAllBindings();
WebContentsImpl* outermost = GetOutermostWebContents();
- if (GetFocusedWebContents() == this && this != outermost) {
+ if (this != outermost && ContainsOrIsFocusedWebContents()) {
// If the current WebContents is in focus, unset it.
- outermost->node_->SetFocusedWebContents(outermost);
+ outermost->SetAsFocusedWebContentsIfNecessary();
}
for (FrameTreeNode* node : frame_tree_.Nodes()) {
@@ -496,8 +506,12 @@ WebContentsImpl::~WebContentsImpl() {
created_widgets_.clear();
// Clear out any JavaScript state.
- if (dialog_manager_)
- dialog_manager_->ResetDialogState(this);
+ if (dialog_manager_) {
+ // This object is being destructed, so make sure that no callbacks happen.
+ dialog_manager_->CancelDialogs(this,
+ true, // suppress_callbacks,
+ true); // reset_state
+ }
if (color_chooser_info_.get())
color_chooser_info_->chooser->End();
@@ -547,26 +561,22 @@ WebContentsImpl::~WebContentsImpl() {
pepper_playback_observer_.reset();
#endif // defined(ENABLED_PLUGINS)
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- FrameDeleted(root->current_frame_host()));
+ for (auto& observer : observers_)
+ observer.FrameDeleted(root->current_frame_host());
if (root->pending_render_view_host()) {
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderViewDeleted(root->pending_render_view_host()));
+ for (auto& observer : observers_)
+ observer.RenderViewDeleted(root->pending_render_view_host());
}
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderViewDeleted(root->current_host()));
+ for (auto& observer : observers_)
+ observer.RenderViewDeleted(root->current_host());
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- WebContentsDestroyed());
+ for (auto& observer : observers_)
+ observer.WebContentsDestroyed();
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- ResetWebContents());
+ for (auto& observer : observers_)
+ observer.ResetWebContents();
SetDelegate(NULL);
}
@@ -674,16 +684,16 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
return true;
}
- base::ObserverListBase<WebContentsObserver>::Iterator it(&observers_);
- WebContentsObserver* observer;
if (render_frame_host) {
- while ((observer = it.GetNext()) != NULL)
- if (observer->OnMessageReceived(message, render_frame_host))
+ for (auto& observer : observers_) {
+ if (observer.OnMessageReceived(message, render_frame_host))
return true;
+ }
} else {
- while ((observer = it.GetNext()) != NULL)
- if (observer->OnMessageReceived(message))
+ for (auto& observer : observers_) {
+ if (observer.OnMessageReceived(message))
return true;
+ }
}
// Message handlers should be aware of which
@@ -900,8 +910,11 @@ int WebContentsImpl::GetRoutingID() const {
}
void WebContentsImpl::CancelActiveAndPendingDialogs() {
- if (dialog_manager_)
- dialog_manager_->CancelActiveAndPendingDialogs(this);
+ if (dialog_manager_) {
+ dialog_manager_->CancelDialogs(this,
+ false, // suppress_callbacks,
+ false); // reset_state
+ }
if (browser_plugin_embedder_)
browser_plugin_embedder_->CancelGuestDialogs();
}
@@ -1024,8 +1037,9 @@ void WebContentsImpl::GetScreenInfo(ScreenInfo* screen_info) {
GetView()->GetScreenInfo(screen_info);
}
-WebUI* WebContentsImpl::CreateSubframeWebUI(const GURL& url,
- const std::string& frame_name) {
+std::unique_ptr<WebUI> WebContentsImpl::CreateSubframeWebUI(
+ const GURL& url,
+ const std::string& frame_name) {
DCHECK(!frame_name.empty());
return CreateWebUI(url, frame_name);
}
@@ -1057,8 +1071,8 @@ void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
if (IsLoading() && entry != NULL && entry->GetIsOverridingUserAgent())
controller_.ReloadBypassingCache(true);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- UserAgentOverrideSet(override));
+ for (auto& observer : observers_)
+ observer.UserAgentOverrideSet(override);
}
const std::string& WebContentsImpl::GetUserAgentOverride() const {
@@ -1140,34 +1154,6 @@ const base::string16& WebContentsImpl::GetTitle() const {
return page_title_when_no_navigation_entry_;
}
-int32_t WebContentsImpl::GetMaxPageID() {
- return GetMaxPageIDForSiteInstance(GetSiteInstance());
-}
-
-int32_t WebContentsImpl::GetMaxPageIDForSiteInstance(
- SiteInstance* site_instance) {
- if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end())
- max_page_ids_[site_instance->GetId()] = -1;
-
- return max_page_ids_[site_instance->GetId()];
-}
-
-void WebContentsImpl::UpdateMaxPageID(int32_t page_id) {
- UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
-}
-
-void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
- SiteInstance* site_instance,
- int32_t page_id) {
- if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
- max_page_ids_[site_instance->GetId()] = page_id;
-}
-
-void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
- WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
- max_page_ids_ = contents->max_page_ids_;
-}
-
SiteInstanceImpl* WebContentsImpl::GetSiteInstance() const {
return GetRenderManager()->current_host()->GetSiteInstance();
}
@@ -1276,11 +1262,10 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
audio_muter_->StopMuting();
}
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidUpdateAudioMutingState(mute));
+ for (auto& observer : observers_)
+ observer.DidUpdateAudioMutingState(mute);
- // Notification for UI updates in response to the changed muting state.
- NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ OnAudioStateChanged(!mute && audio_stream_monitor_.IsCurrentlyAudible());
}
bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
@@ -1340,6 +1325,13 @@ void WebContentsImpl::NotifyNavigationStateChanged(
GetOuterWebContents()->NotifyNavigationStateChanged(changed_flags);
}
+void WebContentsImpl::OnAudioStateChanged(bool is_audible) {
+ SendPageMessage(new PageMsg_AudioStateChanged(MSG_ROUTING_NONE, is_audible));
+
+ // Notification for UI updates in response to the changed audio state.
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+}
+
base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
return last_active_time_;
}
@@ -1348,6 +1340,10 @@ void WebContentsImpl::SetLastActiveTime(base::TimeTicks last_active_time) {
last_active_time_ = last_active_time;
}
+base::TimeTicks WebContentsImpl::GetLastHiddenTime() const {
+ return last_hidden_time_;
+}
+
void WebContentsImpl::WasShown() {
controller_.SetActive(true);
@@ -1364,15 +1360,8 @@ void WebContentsImpl::WasShown() {
last_active_time_ = base::TimeTicks::Now();
- // The resize rect might have changed while this was inactive -- send the new
- // one to make sure it's up to date.
- RenderViewHostImpl* rvh = GetRenderViewHost();
- if (rvh) {
- rvh->GetWidget()->ResizeRectChanged(
- GetRootWindowResizerRect(rvh->GetWidget()));
- }
-
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
+ for (auto& observer : observers_)
+ observer.WasShown();
should_normally_be_visible_ = true;
}
@@ -1395,7 +1384,10 @@ void WebContentsImpl::WasHidden() {
SendPageMessage(new PageMsg_WasHidden(MSG_ROUTING_NONE));
}
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
+ last_hidden_time_ = base::TimeTicks::Now();
+
+ for (auto& observer : observers_)
+ observer.WasHidden();
should_normally_be_visible_ = false;
}
@@ -1477,10 +1469,25 @@ void WebContentsImpl::AttachToOuterWebContentsFrame(
text_input_manager_.reset(nullptr);
}
+void WebContentsImpl::DidChangeVisibleSecurityState() {
+ if (delegate_) {
+ delegate_->VisibleSecurityStateChanged(this);
+
+ SecurityStyleExplanations security_style_explanations;
+ blink::WebSecurityStyle security_style =
+ delegate_->GetSecurityStyle(this, &security_style_explanations);
+ for (auto& observer : observers_) {
+ observer.SecurityStyleChanged(security_style,
+ security_style_explanations);
+ }
+ }
+}
+
void WebContentsImpl::Stop() {
for (FrameTreeNode* node : frame_tree_.Nodes())
node->StopLoading();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
+ for (auto& observer : observers_)
+ observer.NavigationStopped();
}
WebContents* WebContentsImpl::Clone() {
@@ -1492,9 +1499,8 @@ WebContents* WebContentsImpl::Clone() {
WebContentsImpl* tc =
CreateWithOpener(create_params, frame_tree_.root()->opener());
tc->GetController().CopyStateFrom(controller_);
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidCloneToNewWebContents(this, tc));
+ for (auto& observer : observers_)
+ observer.DidCloneToNewWebContents(this, tc);
return tc;
}
@@ -1564,7 +1570,8 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
GetRenderManager()->Init(site_instance.get(), view_routing_id,
params.main_frame_routing_id,
- main_frame_widget_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.
@@ -1741,16 +1748,16 @@ void WebContentsImpl::RenderWidgetDeleted(
fullscreen_widget_process_id_) {
if (delegate_ && delegate_->EmbedsFullscreenWidget())
delegate_->ExitFullscreenModeForTab(this);
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidDestroyFullscreenWidget());
+ for (auto& observer : observers_)
+ observer.DidDestroyFullscreenWidget();
fullscreen_widget_process_id_ = ChildProcessHost::kInvalidUniqueID;
fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
if (fullscreen_widget_had_focus_at_shutdown_)
view_->RestoreFocus();
}
- CHECK(mouse_lock_widget_ != render_widget_host);
+ if (mouse_lock_widget_)
+ LostMouseLock(mouse_lock_widget_);
}
void WebContentsImpl::RenderWidgetGotFocus(
@@ -1769,8 +1776,8 @@ void WebContentsImpl::RenderWidgetWasResized(
if (!rfh || render_widget_host != rfh->GetRenderWidgetHost())
return;
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- MainFrameWasResized(width_changed));
+ for (auto& observer : observers_)
+ observer.MainFrameWasResized(width_changed);
}
void WebContentsImpl::ScreenInfoChanged() {
@@ -1869,6 +1876,10 @@ RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost(
return RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
}
+RenderWidgetHostImpl* WebContentsImpl::GetRenderWidgetHostWithPageFocus() {
+ return GetFocusedWebContents()->GetMainFrame()->GetRenderWidgetHost();
+}
+
void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
// This method is being called to enter renderer-initiated fullscreen mode.
// Make sure any existing fullscreen widget is shut down first.
@@ -1881,9 +1892,8 @@ void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
if (delegate_)
delegate_->EnterFullscreenModeForTab(this, origin);
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(), false));
+ for (auto& observer : observers_)
+ observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(), false);
}
void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
@@ -1919,15 +1929,20 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
}
}
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
- will_cause_resize));
+ for (auto& observer : observers_) {
+ observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
+ will_cause_resize);
+ }
}
bool WebContentsImpl::IsFullscreenForCurrentTab() const {
return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
}
+bool WebContentsImpl::IsFullscreen() {
+ return IsFullscreenForCurrentTab();
+}
+
blink::WebDisplayMode WebContentsImpl::GetDisplayMode(
RenderWidgetHostImpl* render_widget_host) const {
if (!RenderViewHostImpl::From(render_widget_host))
@@ -2065,10 +2080,15 @@ void WebContentsImpl::CreateNewWindow(
// delete the RenderView that had already been created.
Send(new ViewMsg_Close(route_id));
}
+ // Note: even though we're not creating a WebContents here, it could have
+ // been created by the embedder so ensure that the RenderFrameHost is
+ // properly initialized.
// It's safe to only target the frame because the render process will not
// have a chance to create more frames at this point.
- ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI(
- GlobalFrameRoutingId(render_process_id, main_frame_route_id));
+ RenderFrameHostImpl* rfh =
+ RenderFrameHostImpl::FromID(render_process_id, main_frame_route_id);
+ if (rfh)
+ rfh->Init();
return;
}
@@ -2272,9 +2292,8 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
} else {
widget_host_view->InitAsFullscreen(view);
}
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidShowFullscreenWidget());
+ for (auto& observer : observers_)
+ observer.DidShowFullscreenWidget();
if (!widget_host_view->HasFocus())
widget_host_view->Focus();
} else {
@@ -2385,21 +2404,24 @@ bool WebContentsImpl::IsOverridingUserAgent() {
GetController().GetVisibleEntry()->GetIsOverridingUserAgent();
}
+bool WebContentsImpl::IsJavaScriptDialogShowing() const {
+ return is_showing_javascript_dialog_;
+}
+
AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
return accessibility_mode_;
}
void WebContentsImpl::AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) {
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, AccessibilityEventReceived(details));
+ for (auto& observer : observers_)
+ observer.AccessibilityEventReceived(details);
}
void WebContentsImpl::AccessibilityLocationChangesReceived(
const std::vector<AXLocationChangeNotificationDetails>& details) {
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- AccessibilityLocationChangesReceived(details));
+ for (auto& observer : observers_)
+ observer.AccessibilityLocationChangesReceived(details);
}
RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
@@ -2423,7 +2445,7 @@ WebContentsImpl::GetGeolocationServiceContext() {
return geolocation_service_context_.get();
}
-WakeLockServiceContext* WebContentsImpl::GetWakeLockServiceContext() {
+device::WakeLockServiceContext* WebContentsImpl::GetWakeLockServiceContext() {
return wake_lock_service_context_.get();
}
@@ -2460,14 +2482,14 @@ void WebContentsImpl::SendScreenRects() {
MSG_ROUTING_NONE, rwhv->GetBoundsInRootWindow()));
}
- if (browser_plugin_embedder_)
+ if (browser_plugin_embedder_ && !is_being_destroyed_)
browser_plugin_embedder_->DidSendScreenRects();
}
void WebContentsImpl::OnFirstPaintAfterLoad(
RenderWidgetHostImpl* render_widget_host) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidFirstPaintAfterLoad(render_widget_host));
+ for (auto& observer : observers_)
+ observer.DidFirstPaintAfterLoad(render_widget_host);
}
TextInputManager* WebContentsImpl::GetTextInputManager() {
@@ -2480,6 +2502,12 @@ TextInputManager* WebContentsImpl::GetTextInputManager() {
return text_input_manager_.get();
}
+bool WebContentsImpl::OnUpdateDragCursor() {
+ if (browser_plugin_embedder_)
+ return browser_plugin_embedder_->OnUpdateDragCursor();
+ return false;
+}
+
BrowserAccessibilityManager*
WebContentsImpl::GetRootBrowserAccessibilityManager() {
RenderFrameHostImpl* rfh = GetMainFrame();
@@ -2537,14 +2565,6 @@ void WebContentsImpl::ResizeDueToAutoResize(
delegate_->ResizeDueToAutoResize(this, new_size);
}
-bool WebContentsImpl::DisplayedInsecureContent() const {
- return displayed_insecure_content_;
-}
-
-bool WebContentsImpl::DisplayedContentWithCertErrors() const {
- return displayed_content_with_cert_errors_;
-}
-
WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
if (!delegate_)
return NULL;
@@ -2564,8 +2584,8 @@ bool WebContentsImpl::Send(IPC::Message* message) {
void WebContentsImpl::RenderFrameForInterstitialPageCreated(
RenderFrameHost* render_frame_host) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- RenderFrameForInterstitialPageCreated(render_frame_host));
+ for (auto& observer : observers_)
+ observer.RenderFrameForInterstitialPageCreated(render_frame_host);
}
void WebContentsImpl::AttachInterstitialPage(
@@ -2577,8 +2597,8 @@ void WebContentsImpl::AttachInterstitialPage(
// interstitial.
CancelActiveAndPendingDialogs();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidAttachInterstitialPage());
+ for (auto& observer : observers_)
+ observer.DidAttachInterstitialPage();
// Stop the throbber if needed while the interstitial page is shown.
if (frame_tree_.IsLoading())
@@ -2601,8 +2621,8 @@ void WebContentsImpl::DetachInterstitialPage() {
GetRenderManager()->interstitial_page()->pause_throbber();
if (ShowingInterstitialPage())
GetRenderManager()->remove_interstitial_page();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidDetachInterstitialPage());
+ for (auto& observer : observers_)
+ observer.DidDetachInterstitialPage();
// Restart the throbber if needed now that the interstitial page is going
// away.
@@ -2953,14 +2973,20 @@ void WebContentsImpl::Close() {
Close(GetRenderViewHost());
}
-void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
- int screen_x, int screen_y, blink::WebDragOperation operation) {
+void WebContentsImpl::DragSourceEndedAt(int client_x,
+ int client_y,
+ int screen_x,
+ int screen_y,
+ blink::WebDragOperation operation,
+ RenderWidgetHost* source_rwh) {
if (browser_plugin_embedder_.get())
- browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
- screen_x, screen_y, operation);
- if (GetRenderViewHost())
- GetRenderViewHost()->DragSourceEndedAt(client_x, client_y, screen_x,
- screen_y, operation);
+ browser_plugin_embedder_->DragSourceEndedAt(
+ client_x, client_y, screen_x, screen_y, operation);
+ if (source_rwh) {
+ source_rwh->DragSourceEndedAt(gfx::Point(client_x, client_y),
+ gfx::Point(screen_x, screen_y),
+ operation);
+ }
}
void WebContentsImpl::LoadStateChanged(
@@ -2990,16 +3016,14 @@ void WebContentsImpl::DidGetResourceResponseStart(
controller_.ssl_manager()->DidStartResourceResponse(
details.url, details.has_certificate, details.ssl_cert_status);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidGetResourceResponseStart(details));
+ for (auto& observer : observers_)
+ observer.DidGetResourceResponseStart(details);
}
void WebContentsImpl::DidGetRedirectForResourceRequest(
const ResourceRedirectDetails& details) {
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidGetRedirectForResourceRequest(details));
+ for (auto& observer : observers_)
+ observer.DidGetRedirectForResourceRequest(details);
// TODO(avi): Remove. http://crbug.com/170921
NotificationService::current()->Notify(
@@ -3009,12 +3033,13 @@ void WebContentsImpl::DidGetRedirectForResourceRequest(
}
void WebContentsImpl::NotifyWebContentsFocused() {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, OnWebContentsFocused());
+ for (auto& observer : observers_)
+ observer.OnWebContentsFocused();
}
-void WebContentsImpl::SystemDragEnded() {
- if (GetRenderViewHost())
- GetRenderViewHost()->DragSourceSystemDragEnded();
+void WebContentsImpl::SystemDragEnded(RenderWidgetHost* source_rwh) {
+ if (source_rwh)
+ source_rwh->DragSourceSystemDragEnded();
if (browser_plugin_embedder_.get())
browser_plugin_embedder_->SystemDragEnded();
}
@@ -3232,7 +3257,7 @@ bool WebContentsImpl::FocusLocationBarByDefault() {
NavigationEntryImpl* entry = controller_.GetPendingEntry();
if (controller_.IsInitialNavigation() && entry &&
!entry->is_renderer_initiated() &&
- entry->GetURL() == GURL(url::kAboutBlankURL)) {
+ entry->GetURL() == url::kAboutBlankURL) {
return true;
}
return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
@@ -3244,25 +3269,25 @@ void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
}
void WebContentsImpl::DidStartNavigation(NavigationHandle* navigation_handle) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidStartNavigation(navigation_handle));
+ for (auto& observer : observers_)
+ observer.DidStartNavigation(navigation_handle);
}
void WebContentsImpl::DidRedirectNavigation(
NavigationHandle* navigation_handle) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidRedirectNavigation(navigation_handle));
+ for (auto& observer : observers_)
+ observer.DidRedirectNavigation(navigation_handle);
}
void WebContentsImpl::ReadyToCommitNavigation(
NavigationHandle* navigation_handle) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- ReadyToCommitNavigation(navigation_handle));
+ for (auto& observer : observers_)
+ observer.ReadyToCommitNavigation(navigation_handle);
}
void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidFinishNavigation(navigation_handle));
+ for (auto& observer : observers_)
+ observer.DidFinishNavigation(navigation_handle);
}
void WebContentsImpl::DidStartProvisionalLoad(
@@ -3271,11 +3296,10 @@ void WebContentsImpl::DidStartProvisionalLoad(
bool is_error_page,
bool is_iframe_srcdoc) {
// Notify observers about the start of the provisional load.
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidStartProvisionalLoadForFrame(
- render_frame_host, validated_url, is_error_page, is_iframe_srcdoc));
+ for (auto& observer : observers_) {
+ observer.DidStartProvisionalLoadForFrame(render_frame_host, validated_url,
+ is_error_page, is_iframe_srcdoc);
+ }
// Notify accessibility if this is a reload.
NavigationEntry* entry = controller_.GetVisibleEntry();
@@ -3295,10 +3319,11 @@ void WebContentsImpl::DidFailProvisionalLoadWithError(
int error_code,
const base::string16& error_description,
bool was_ignored_by_handler) {
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_,
- DidFailProvisionalLoad(render_frame_host, validated_url, error_code,
- error_description, was_ignored_by_handler));
+ for (auto& observer : observers_) {
+ observer.DidFailProvisionalLoad(render_frame_host, validated_url,
+ error_code, error_description,
+ was_ignored_by_handler);
+ }
FrameTreeNode* ftn = render_frame_host->frame_tree_node();
BrowserAccessibilityManager* manager =
@@ -3313,11 +3338,10 @@ void WebContentsImpl::DidFailLoadWithError(
int error_code,
const base::string16& error_description,
bool was_ignored_by_handler) {
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidFailLoad(render_frame_host, url, error_code, error_description,
- was_ignored_by_handler));
+ for (auto& observer : observers_) {
+ observer.DidFailLoad(render_frame_host, url, error_code, error_description,
+ was_ignored_by_handler);
+ }
}
void WebContentsImpl::NotifyChangedNavigationState(
@@ -3328,10 +3352,8 @@ void WebContentsImpl::NotifyChangedNavigationState(
void WebContentsImpl::DidStartNavigationToPendingEntry(const GURL& url,
ReloadType reload_type) {
// Notify observers about navigation.
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidStartNavigationToPendingEntry(url, reload_type));
+ for (auto& observer : observers_)
+ observer.DidStartNavigationToPendingEntry(url, reload_type);
}
void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
@@ -3345,13 +3367,11 @@ void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
if (new_contents && RenderFrameHost::FromID(process_id, frame_id)) {
// Notify observers.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidOpenRequestedURL(new_contents,
- render_frame_host,
- params.url,
- params.referrer,
- params.disposition,
- params.transition));
+ for (auto& observer : observers_) {
+ observer.DidOpenRequestedURL(new_contents, render_frame_host, params.url,
+ params.referrer, params.disposition,
+ params.transition);
+ }
}
}
@@ -3372,10 +3392,10 @@ void WebContentsImpl::DidCommitProvisionalLoad(
const GURL& url,
ui::PageTransition transition_type) {
// Notify observers about the commit of the provisional load.
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidCommitProvisionalLoadForFrame(
- render_frame_host, url, transition_type));
+ for (auto& observer : observers_) {
+ observer.DidCommitProvisionalLoadForFrame(render_frame_host, url,
+ transition_type);
+ }
BrowserAccessibilityManager* manager =
render_frame_host->browser_accessibility_manager();
@@ -3421,18 +3441,9 @@ void WebContentsImpl::DidNavigateMainFramePostCommit(
theme_color_ = SK_ColorTRANSPARENT;
}
- if (!details.is_in_page) {
- // Once the main frame is navigated, we're no longer considered to have
- // displayed insecure content.
- displayed_insecure_content_ = false;
- displayed_content_with_cert_errors_ = false;
- SSLManager::NotifySSLInternalStateChanged(
- GetController().GetBrowserContext());
- }
-
// Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidNavigateMainFrame(details, params));
+ for (auto& observer : observers_)
+ observer.DidNavigateMainFrame(details, params);
if (delegate_)
delegate_->DidNavigateMainFramePostCommit(this);
@@ -3453,12 +3464,15 @@ void WebContentsImpl::DidNavigateAnyFramePostCommit(
// If this is a user-initiated navigation, start allowing JavaScript dialogs
// again.
- if (params.gesture == NavigationGestureUser && dialog_manager_)
- dialog_manager_->ResetDialogState(this);
+ if (params.gesture == NavigationGestureUser && dialog_manager_) {
+ dialog_manager_->CancelDialogs(this,
+ false, // suppress_callbacks,
+ true); // reset_state
+ }
// Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidNavigateAnyFrame(render_frame_host, details, params));
+ for (auto& observer : observers_)
+ observer.DidNavigateAnyFrame(render_frame_host, details, params);
}
void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
@@ -3483,8 +3497,8 @@ void WebContentsImpl::OnThemeColorChanged(SkColor theme_color) {
if (did_first_visually_non_empty_paint_ &&
last_sent_theme_color_ != theme_color_) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidChangeThemeColor(theme_color_));
+ for (auto& observer : observers_)
+ observer.DidChangeThemeColor(theme_color_);
last_sent_theme_color_ = theme_color_;
}
}
@@ -3494,9 +3508,8 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
const std::string& http_method,
const std::string& mime_type,
ResourceType resource_type) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidLoadResourceFromMemoryCache(url, mime_type,
- resource_type));
+ for (auto& observer : observers_)
+ observer.DidLoadResourceFromMemoryCache(url, mime_type, resource_type);
if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
scoped_refptr<net::URLRequestContextGetter> request_context(
@@ -3514,9 +3527,7 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
void WebContentsImpl::OnDidDisplayInsecureContent() {
RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
- displayed_insecure_content_ = true;
- SSLManager::NotifySSLInternalStateChanged(
- GetController().GetBrowserContext());
+ controller_.ssl_manager()->DidDisplayMixedContent();
}
void WebContentsImpl::OnDidRunInsecureContent(const GURL& security_origin,
@@ -3527,16 +3538,12 @@ void WebContentsImpl::OnDidRunInsecureContent(const GURL& security_origin,
if (base::EndsWith(security_origin.spec(), kDotGoogleDotCom,
base::CompareCase::INSENSITIVE_ASCII))
RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
- controller_.ssl_manager()->DidRunInsecureContent(security_origin);
- SSLManager::NotifySSLInternalStateChanged(
- GetController().GetBrowserContext());
+ controller_.ssl_manager()->DidRunMixedContent(security_origin);
}
void WebContentsImpl::OnDidDisplayContentWithCertificateErrors(
const GURL& url) {
- displayed_content_with_cert_errors_ = true;
- SSLManager::NotifySSLInternalStateChanged(
- GetController().GetBrowserContext());
+ controller_.ssl_manager()->DidDisplayContentWithCertErrors();
}
void WebContentsImpl::OnDidRunContentWithCertificateErrors(
@@ -3549,8 +3556,6 @@ void WebContentsImpl::OnDidRunContentWithCertificateErrors(
// about:blank and sandboxed origins. https://crbug.com/609527
controller_.ssl_manager()->DidRunContentWithCertErrors(
entry->GetURL().GetOrigin());
- SSLManager::NotifySSLInternalStateChanged(
- GetController().GetBrowserContext());
}
void WebContentsImpl::OnDocumentLoadedInFrame() {
@@ -3559,8 +3564,8 @@ void WebContentsImpl::OnDocumentLoadedInFrame() {
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, DocumentLoadedInFrame(rfh));
+ for (auto& observer : observers_)
+ observer.DocumentLoadedInFrame(rfh);
}
void WebContentsImpl::OnDidFinishLoad(const GURL& url) {
@@ -3574,8 +3579,8 @@ void WebContentsImpl::OnDidFinishLoad(const GURL& url) {
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
+ for (auto& observer : observers_)
+ observer.DidFinishLoad(rfh, validated_url);
}
void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
@@ -3604,9 +3609,8 @@ void WebContentsImpl::OnPageScaleFactorChanged(float page_scale_factor) {
}
}
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- OnPageScaleFactorChanged(page_scale_factor));
+ for (auto& observer : observers_)
+ observer.OnPageScaleFactorChanged(page_scale_factor);
}
void WebContentsImpl::OnEnumerateDirectory(int request_id,
@@ -3707,8 +3711,8 @@ void WebContentsImpl::OnDomOperationResponse(const std::string& json_string) {
void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
bool blocked_by_policy) {
// Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- AppCacheAccessed(manifest_url, blocked_by_policy));
+ for (auto& observer : observers_)
+ observer.AppCacheAccessed(manifest_url, blocked_by_policy);
}
void WebContentsImpl::OnOpenColorChooser(
@@ -3757,14 +3761,14 @@ void WebContentsImpl::OnWebUISend(const GURL& source_url,
#if defined(ENABLE_PLUGINS)
void WebContentsImpl::OnPepperInstanceCreated(int32_t pp_instance) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PepperInstanceCreated());
+ for (auto& observer : observers_)
+ observer.PepperInstanceCreated();
pepper_playback_observer_->PepperInstanceCreated(pp_instance);
}
void WebContentsImpl::OnPepperInstanceDeleted(int32_t pp_instance) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PepperInstanceDeleted());
+ for (auto& observer : observers_)
+ observer.PepperInstanceDeleted();
pepper_playback_observer_->PepperInstanceDeleted(pp_instance);
}
@@ -3773,8 +3777,8 @@ void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
bool is_hung) {
UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PluginHungStatusChanged(plugin_child_id, path, is_hung));
+ for (auto& observer : observers_)
+ observer.PluginHungStatusChanged(plugin_child_id, path, is_hung);
}
void WebContentsImpl::OnPepperStartsPlayback(int32_t pp_instance) {
@@ -3787,8 +3791,8 @@ void WebContentsImpl::OnPepperStopsPlayback(int32_t pp_instance) {
void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PluginCrashed(plugin_path, plugin_pid));
+ for (auto& observer : observers_)
+ observer.PluginCrashed(plugin_path, plugin_pid);
}
void WebContentsImpl::OnRequestPpapiBrokerPermission(
@@ -3833,60 +3837,43 @@ void WebContentsImpl::OnUpdateFaviconURL(
if (!rvhi->is_active())
return;
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidUpdateFaviconURL(candidates));
+ for (auto& observer : observers_)
+ observer.DidUpdateFaviconURL(candidates);
}
-void WebContentsImpl::OnMediaSessionStateChanged() {
- MediaSession* session = MediaSession::Get(this);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- MediaSessionStateChanged(session->IsControllable(),
- session->IsSuspended(),
- session->metadata()));
+void WebContentsImpl::OnPasswordInputShownOnHttp() {
+ controller_.ssl_manager()->DidShowPasswordInputOnHttp();
}
-void WebContentsImpl::ResumeMediaSession() {
- MediaSession::Get(this)->Resume(MediaSession::SuspendType::UI);
+void WebContentsImpl::OnAllPasswordInputsHiddenOnHttp() {
+ controller_.ssl_manager()->DidHideAllPasswordInputsOnHttp();
}
-void WebContentsImpl::SuspendMediaSession() {
- MediaSession::Get(this)->Suspend(MediaSession::SuspendType::UI);
+void WebContentsImpl::OnCreditCardInputShownOnHttp() {
+ controller_.ssl_manager()->DidShowCreditCardInputOnHttp();
}
-void WebContentsImpl::StopMediaSession() {
- MediaSession::Get(this)->Stop(MediaSession::SuspendType::UI);
+void WebContentsImpl::SetIsOverlayContent(bool is_overlay_content) {
+ is_overlay_content_ = is_overlay_content;
}
void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidFirstVisuallyNonEmptyPaint());
+ for (auto& observer : observers_)
+ observer.DidFirstVisuallyNonEmptyPaint();
did_first_visually_non_empty_paint_ = true;
if (theme_color_ != last_sent_theme_color_) {
// Theme color should have updated by now if there was one.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidChangeThemeColor(theme_color_));
+ for (auto& observer : observers_)
+ observer.DidChangeThemeColor(theme_color_);
last_sent_theme_color_ = theme_color_;
}
}
-void WebContentsImpl::DidChangeVisibleSSLState() {
- if (delegate_) {
- delegate_->VisibleSSLStateChanged(this);
-
- SecurityStyleExplanations security_style_explanations;
- SecurityStyle security_style =
- delegate_->GetSecurityStyle(this, &security_style_explanations);
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_,
- SecurityStyleChanged(security_style, security_style_explanations));
- }
-}
-
void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- BeforeFormRepostWarningShow());
+ for (auto& observer : observers_)
+ observer.BeforeFormRepostWarningShow();
}
void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
@@ -3899,20 +3886,6 @@ bool WebContentsImpl::HasAccessedInitialDocument() {
return has_accessed_initial_document_;
}
-void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
- // If we are creating a RVH for a restored controller, then we need to make
- // sure the RenderView starts with a next_page_id_ larger than the number
- // of restored entries. This must be called before the RenderView starts
- // navigating (to avoid a race between the browser updating max_page_id and
- // the renderer updating next_page_id_). Because of this, we only call this
- // from CreateRenderView and allow that to notify the RenderView for us.
- int max_restored_page_id = controller_.GetMaxRestoredPageID();
- if (max_restored_page_id >
- GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
- UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
- max_restored_page_id);
-}
-
void WebContentsImpl::UpdateTitleForEntry(NavigationEntry* entry,
const base::string16& title) {
// For file URLs without a title, use the pathname instead. In the case of a
@@ -3946,8 +3919,8 @@ void WebContentsImpl::UpdateTitleForEntry(NavigationEntry* entry,
// Lastly, set the title for the view.
view_->SetPageTitle(final_title);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- TitleWasSet(entry, explicit_set));
+ for (auto& observer : observers_)
+ observer.TitleWasSet(entry, explicit_set);
// Broadcast notifications when the UI should be updated.
if (entry == controller_.GetEntryAtOffset(0))
@@ -4003,11 +3976,13 @@ void WebContentsImpl::LoadingStateChanged(bool to_different_document,
TRACE_EVENT_ASYNC_BEGIN2("browser,navigation", "WebContentsImpl Loading",
this, "URL", url, "Main FrameTreeNode id",
GetFrameTree()->root()->frame_tree_node_id());
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStartLoading());
+ for (auto& observer : observers_)
+ observer.DidStartLoading();
} else {
TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
this, "URL", url);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStopLoading());
+ for (auto& observer : observers_)
+ observer.DidStopLoading();
}
// TODO(avi): Remove. http://crbug.com/170921
@@ -4025,8 +4000,8 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
// notification so that clients that pick up a pointer to |this| can NULL the
// pointer. See Bug 1230284.
notify_disconnection_ = true;
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- RenderViewHostChanged(old_host, new_host));
+ for (auto& observer : observers_)
+ observer.RenderViewHostChanged(old_host, new_host);
// Ensure that the associated embedder gets cleared after a RenderViewHost
// gets swapped, so we don't reuse the same embedder next time a
@@ -4036,9 +4011,20 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
RenderFrameHost* new_host) {
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderFrameHostChanged(old_host, new_host));
+ // Copies the background color from an old WebContents to a new one that
+ // replaces it on the screen. This allows the new WebContents to use the
+ // old one's background color as the starting background color, before having
+ // loaded any contents. As a result, we avoid flashing white when navigating
+ // from a site whith a dark background to another site with a dark background.
+ if (old_host && new_host) {
+ RenderWidgetHostView* old_view = old_host->GetView();
+ RenderWidgetHostView* new_view = new_host->GetView();
+ if (old_view && new_view)
+ new_view->SetBackgroundColor(old_view->background_color());
+ }
+
+ for (auto& observer : observers_)
+ observer.RenderFrameHostChanged(old_host, new_host);
}
// TODO(avi): Remove this entire function because this notification is already
@@ -4056,8 +4042,8 @@ void WebContentsImpl::NotifyDisconnected() {
void WebContentsImpl::NotifyNavigationEntryCommitted(
const LoadCommittedDetails& load_details) {
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
+ for (auto& observer : observers_)
+ observer.NavigationEntryCommitted(load_details);
}
bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
@@ -4079,9 +4065,8 @@ const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const {
}
void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderFrameCreated(render_frame_host));
+ for (auto& observer : observers_)
+ observer.RenderFrameCreated(render_frame_host);
SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
if (!render_frame_host->IsRenderFrameLive() || render_frame_host->GetParent())
@@ -4100,9 +4085,8 @@ void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
}
void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderFrameDeleted(render_frame_host));
+ for (auto& observer : observers_)
+ observer.RenderFrameDeleted(render_frame_host);
}
void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
@@ -4132,6 +4116,7 @@ void WebContentsImpl::RunJavaScriptMessage(
!delegate_->GetJavaScriptDialogManager(this);
if (!suppress_this_message) {
+ is_showing_javascript_dialog_ = true;
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
dialog_manager_->RunJavaScriptDialog(
this, frame_url, javascript_message_type, message, default_prompt,
@@ -4202,6 +4187,20 @@ double WebContentsImpl::GetPendingPageZoomLevel() {
url.scheme(), net::GetHostOrSpecFromURL(url));
}
+bool WebContentsImpl::HideDownloadUI() const {
+ return is_overlay_content_;
+}
+
+bool WebContentsImpl::IsFocusedElementEditable() {
+ RenderFrameHostImpl* frame = GetFocusedFrame();
+ return frame && frame->has_focused_editable_element();
+}
+
+void WebContentsImpl::ClearFocusedElement() {
+ if (auto* frame = GetFocusedFrame())
+ frame->ClearFocusedElement();
+}
+
bool WebContentsImpl::IsNeverVisible() {
if (!delegate_)
return false;
@@ -4217,16 +4216,6 @@ RendererPreferences WebContentsImpl::GetRendererPrefs(
return renderer_preferences_;
}
-gfx::Rect WebContentsImpl::GetRootWindowResizerRect(
- RenderWidgetHostImpl* render_widget_host) const {
- if (!RenderViewHostImpl::From(render_widget_host))
- return gfx::Rect();
-
- if (delegate_)
- return delegate_->GetRootWindowResizerRect();
- return gfx::Rect();
-}
-
void WebContentsImpl::RemoveBrowserPluginEmbedder() {
if (browser_plugin_embedder_)
browser_plugin_embedder_.reset();
@@ -4257,6 +4246,17 @@ WebContentsImpl* WebContentsImpl::GetFocusedWebContents() {
return outermost->node_->focused_web_contents();
}
+bool WebContentsImpl::ContainsOrIsFocusedWebContents() {
+ for (WebContentsImpl* focused_contents = GetFocusedWebContents();
+ focused_contents;
+ focused_contents = focused_contents->GetOuterWebContents()) {
+ if (focused_contents == this)
+ return true;
+ }
+
+ return false;
+}
+
WebContentsImpl* WebContentsImpl::GetOutermostWebContents() {
WebContentsImpl* root = this;
while (root->GetOuterWebContents())
@@ -4281,8 +4281,9 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
view_->RenderViewCreated(render_view_host);
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, RenderViewCreated(render_view_host));
+ for (auto& observer : observers_)
+ observer.RenderViewCreated(render_view_host);
+ RenderFrameDevToolsAgentHost::WebContentsCreated(this);
}
void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
@@ -4309,7 +4310,8 @@ void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
view_->Focus();
}
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
+ for (auto& observer : observers_)
+ observer.RenderViewReady();
}
void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
@@ -4339,17 +4341,16 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
NotifyDisconnected();
SetIsCrashed(status, error_code);
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- RenderProcessGone(GetCrashedStatus()));
+ for (auto& observer : observers_)
+ observer.RenderProcessGone(GetCrashedStatus());
}
void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
+ for (auto& observer : observers_)
+ observer.RenderViewDeleted(rvh);
}
void WebContentsImpl::UpdateState(RenderViewHost* rvh,
- int32_t page_id,
const PageState& page_state) {
DCHECK(!SiteIsolationPolicy::UseSubframeNavigationEntries());
@@ -4359,27 +4360,17 @@ void WebContentsImpl::UpdateState(RenderViewHost* rvh,
if (rvh->GetDelegate()->GetAsWebContents() != this)
return;
- // We must be prepared to handle state updates for any page. They occur
- // when the user is scrolling and entering form data, as well as when we're
- // leaving a page, in which case our state may have already been moved to
- // the next page. The navigation controller will look up the appropriate
- // NavigationEntry and update it when it is notified via the delegate.
- RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
- NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
- rvhi->GetSiteInstance(), page_id);
- if (!entry)
+ if (!rvh->GetMainFrame()) {
+ // When UseSubframeNavigationEntries is turned off, state updates only come
+ // in on main frames. When UseSubframeNavigationEntries is turned on,
+ // UpdateStateForFrame() should have been called rather than this function.
+ NOTREACHED();
return;
-
- // Sanity check that ensures nav_entry_id and page_id point to the same
- // navigation entry.
- if (rvhi->GetMainFrame()) {
- NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID(
- static_cast<RenderFrameHostImpl*>(rvhi->GetMainFrame())
- ->nav_entry_id());
-
- DCHECK_EQ(entry, new_entry);
}
+ NavigationEntryImpl* entry = controller_.GetEntryWithUniqueID(
+ static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame())->nav_entry_id());
+
if (page_state == entry->GetPageState())
return; // Nothing to update.
entry->SetPageState(page_state);
@@ -4530,14 +4521,14 @@ void WebContentsImpl::DidAccessInitialDocument() {
void WebContentsImpl::DidChangeName(RenderFrameHost* render_frame_host,
const std::string& name) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- FrameNameChanged(render_frame_host, name));
+ for (auto& observer : observers_)
+ observer.FrameNameChanged(render_frame_host, name);
}
void WebContentsImpl::DocumentOnLoadCompleted(
RenderFrameHost* render_frame_host) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DocumentOnLoadCompletedInMainFrame());
+ for (auto& observer : observers_)
+ observer.DocumentOnLoadCompletedInMainFrame();
// TODO(avi): Remove. http://crbug.com/170921
NotificationService::current()->Notify(
@@ -4602,7 +4593,6 @@ void WebContentsImpl::UpdateStateForFrame(RenderFrameHost* render_frame_host,
}
void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
- int32_t page_id,
const base::string16& title,
base::i18n::TextDirection title_direction) {
// If we have a title, that's a pretty good indication that we've started
@@ -4611,20 +4601,8 @@ void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
// Try to find the navigation entry, which might not be the current one.
// For example, it might be from a recently swapped out RFH.
- NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
- render_frame_host->GetSiteInstance(), page_id);
-
- NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID(
+ NavigationEntryImpl* entry = controller_.GetEntryWithUniqueID(
static_cast<RenderFrameHostImpl*>(render_frame_host)->nav_entry_id());
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
- // In out-of-process iframe enabled modes, page_id can't keep track of
- // navigations in other processes, so we must use nav_entry_id.
- // TODO(creis): Switch to use this as the default.
- entry = new_entry;
- }
- // (In modes that have no out-of-process iframes, nav_entry_id and page_id
- // will usually agree on which entry to update, but may disagree if commits
- // from a previous RFH have been ignored, resetting the RFH's nav_entry_id.)
// We can handle title updates when we don't have an entry in
// UpdateTitleForEntry, but only if the update is from the current RVH.
@@ -4644,8 +4622,8 @@ void WebContentsImpl::UpdateEncoding(RenderFrameHost* render_frame_host,
void WebContentsImpl::DocumentAvailableInMainFrame(
RenderViewHost* render_view_host) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DocumentAvailableInMainFrame());
+ for (auto& observer : observers_)
+ observer.DocumentAvailableInMainFrame();
}
void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
@@ -4698,39 +4676,69 @@ void WebContentsImpl::EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) {
}
}
+void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
+ // Only change focus if we are not currently focused.
+ WebContentsImpl* old_contents = GetFocusedWebContents();
+ if (old_contents == this)
+ return;
+
+ // Send a page level blur to the old contents so that it displays inactive UI
+ // and focus this contents to activate it.
+ if (old_contents)
+ old_contents->GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(false);
+ GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(true);
+ GetOutermostWebContents()->node_->SetFocusedWebContents(this);
+}
+
void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
SiteInstance* source) {
+ // The PDF plugin still runs as a BrowserPlugin and must go through the
+ // input redirection mechanism. It must not become focused direcly.
if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) {
frame_tree_.SetFocusedFrame(node, source);
return;
}
- // 1. Find old focused frame and unfocus it.
- // 2. Focus the new frame in the current FrameTree.
- // 3. Set current WebContents as focused.
- WebContentsImpl* old_focused_contents = GetFocusedWebContents();
- if (old_focused_contents != this) {
- // Focus is moving between frame trees, unfocus the frame in the old tree.
- old_focused_contents->frame_tree_.SetFocusedFrame(nullptr, source);
- GetOutermostWebContents()->node_->SetFocusedWebContents(this);
- }
+ SetAsFocusedWebContentsIfNecessary();
frame_tree_.SetFocusedFrame(node, source);
+}
+
+void WebContentsImpl::OnFocusedElementChangedInFrame(
+ RenderFrameHostImpl* frame,
+ const gfx::Rect& bounds_in_root_view) {
+ RenderWidgetHostViewBase* root_view =
+ static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
+ if (!root_view || !frame->GetView())
+ return;
+
+ // Converting to screen coordinates.
+ gfx::Point origin = bounds_in_root_view.origin();
+ origin += root_view->GetViewBounds().OffsetFromOrigin();
+ gfx::Rect bounds_in_screen(origin, bounds_in_root_view.size());
+
+ root_view->FocusedNodeChanged(frame->has_focused_editable_element(),
+ bounds_in_screen);
+
+ FocusedNodeDetails details = {frame->has_focused_editable_element(),
+ bounds_in_screen};
- // TODO(avallee): Remove this once page focus is fixed.
- RenderWidgetHostImpl* rwh = node->current_frame_host()->GetRenderWidgetHost();
- if (rwh && old_focused_contents != this)
- rwh->Focus();
+ // TODO(ekaramad): We should replace this with an observer notification
+ // (https://crbug.com/675975).
+ NotificationService::current()->Notify(
+ NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
+ Source<RenderViewHost>(GetRenderViewHost()),
+ Details<FocusedNodeDetails>(&details));
}
-bool WebContentsImpl::AddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) {
+bool WebContentsImpl::DidAddMessageToConsole(int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) {
if (!delegate_)
return false;
- return delegate_->AddMessageToConsole(this, level, message, line_no,
- source_id);
+ return delegate_->DidAddMessageToConsole(this, level, message, line_no,
+ source_id);
}
void WebContentsImpl::OnUserInteraction(
@@ -4740,8 +4748,8 @@ void WebContentsImpl::OnUserInteraction(
if (!HasMatchingWidgetHost(&frame_tree_, render_widget_host))
return;
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidGetUserInteraction(type));
+ for (auto& observer : observers_)
+ observer.DidGetUserInteraction(type);
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
// Exclude scroll events as user gestures for resource load dispatches.
@@ -4750,16 +4758,34 @@ void WebContentsImpl::OnUserInteraction(
rdh->OnUserGesture();
}
+void WebContentsImpl::FocusOwningWebContents(
+ RenderWidgetHostImpl* render_widget_host) {
+ // The PDF plugin still runs as a BrowserPlugin and must go through the
+ // input redirection mechanism. It must not become focused direcly.
+ if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_)
+ return;
+
+ RenderWidgetHostImpl* focused_widget =
+ GetFocusedRenderWidgetHost(render_widget_host);
+
+ if (focused_widget != render_widget_host &&
+ (!focused_widget ||
+ focused_widget->delegate() != render_widget_host->delegate())) {
+ SetAsFocusedWebContentsIfNecessary();
+ }
+}
+
void WebContentsImpl::OnIgnoredUIEvent() {
// Notify observers.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
+ for (auto& observer : observers_)
+ observer.DidGetIgnoredUIEvent();
}
void WebContentsImpl::RendererUnresponsive(
RenderWidgetHostImpl* render_widget_host,
- RenderWidgetHostDelegate::RendererUnresponsiveType type) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- OnRendererUnresponsive(render_widget_host));
+ RendererUnresponsiveType type) {
+ for (auto& observer : observers_)
+ observer.OnRendererUnresponsive(render_widget_host);
// Don't show hung renderer dialog for a swapped out RVH.
if (render_widget_host != GetRenderViewHost()->GetWidget())
@@ -4777,7 +4803,7 @@ void WebContentsImpl::RendererUnresponsive(
// Record histograms about the type of renderer hang.
UMA_HISTOGRAM_ENUMERATION(
"ChildProcess.HangRendererType", type,
- RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_MAX);
+ RendererUnresponsiveType::RENDERER_UNRESPONSIVE_MAX);
// We might have been waiting for both beforeunload and unload ACK.
// Check if tab is to be unloaded first.
@@ -4807,8 +4833,16 @@ void WebContentsImpl::RendererUnresponsive(
if (!GetRenderViewHost() || !GetRenderViewHost()->IsRenderViewLive())
return;
- if (delegate_)
- delegate_->RendererUnresponsive(this);
+ if (delegate_) {
+ WebContentsUnresponsiveState unresponsive_state;
+ unresponsive_state.reason = type;
+ unresponsive_state.outstanding_ack_count =
+ render_widget_host->in_flight_event_count();
+ unresponsive_state.outstanding_event_type =
+ render_widget_host->hang_monitor_event_type();
+ unresponsive_state.last_event_type = render_widget_host->last_event_type();
+ delegate_->RendererUnresponsive(this, unresponsive_state);
+ }
}
void WebContentsImpl::RendererResponsive(
@@ -4823,8 +4857,8 @@ void WebContentsImpl::RendererResponsive(
void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
bool proceed, const base::TimeTicks& proceed_time,
bool* proceed_to_fire_unload) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- BeforeUnloadFired(proceed_time));
+ for (auto& observer : observers_)
+ observer.BeforeUnloadFired(proceed_time);
if (delegate_)
delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
// Note: |this| might be deleted at this point.
@@ -4856,8 +4890,11 @@ void WebContentsImpl::CancelModalDialogsForRenderManager() {
// Note that we don't bother telling browser_plugin_embedder_ because the
// cross-process navigation will either destroy the browser plugins or not
// require their dialogs to close.
- if (dialog_manager_)
- dialog_manager_->ResetDialogState(this);
+ if (dialog_manager_) {
+ dialog_manager_->CancelDialogs(this,
+ false, // suppress_callbacks,
+ true); // reset_state
+ }
}
void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
@@ -4889,8 +4926,7 @@ NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
std::unique_ptr<WebUIImpl> WebContentsImpl::CreateWebUIForRenderFrameHost(
const GURL& url) {
- return std::unique_ptr<WebUIImpl>(
- static_cast<WebUIImpl*>(CreateWebUI(url, std::string())));
+ return CreateWebUI(url, std::string());
}
NavigationEntry*
@@ -4919,14 +4955,10 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
if (proxy_routing_id == MSG_ROUTING_NONE)
CreateRenderWidgetHostViewForRenderManager(render_view_host);
- // Make sure we use the correct starting page_id in the new RenderView.
- UpdateMaxPageIDIfNecessary(render_view_host);
- int32_t max_page_id =
- GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
-
if (!static_cast<RenderViewHostImpl*>(render_view_host)
- ->CreateRenderView(opener_frame_routing_id, proxy_routing_id,
- max_page_id, replicated_frame_state,
+ ->CreateRenderView(opener_frame_routing_id,
+ proxy_routing_id,
+ replicated_frame_state,
created_with_opener_)) {
return false;
}
@@ -5003,11 +5035,11 @@ bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
frame_tree_.root()->current_replication_state());
}
-shell::InterfaceProvider* WebContentsImpl::GetJavaInterfaces() {
+service_manager::InterfaceProvider* WebContentsImpl::GetJavaInterfaces() {
if (!java_interfaces_) {
- shell::mojom::InterfaceProviderPtr provider;
+ service_manager::mojom::InterfaceProviderPtr provider;
BindInterfaceRegistryForWebContents(mojo::GetProxy(&provider), this);
- java_interfaces_.reset(new shell::InterfaceProvider);
+ java_interfaces_.reset(new service_manager::InterfaceProvider);
java_interfaces_->Bind(std::move(provider));
}
return java_interfaces_.get();
@@ -5053,10 +5085,11 @@ void WebContentsImpl::OnDialogClosed(int render_process_id,
controller_.DiscardNonCommittedEntries();
}
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- BeforeUnloadDialogCancelled());
+ for (auto& observer : observers_)
+ observer.BeforeUnloadDialogCancelled();
}
+ is_showing_javascript_dialog_ = false;
is_showing_before_unload_dialog_ = false;
if (rfh) {
rfh->JavaScriptDialogClosed(reply_msg, success, user_input,
@@ -5126,8 +5159,8 @@ gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
}
void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
- FOR_EACH_OBSERVER(
- WebContentsObserver, observers_, FrameDeleted(render_frame_host));
+ for (auto& observer : observers_)
+ observer.FrameDeleted(render_frame_host);
}
void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
@@ -5138,19 +5171,21 @@ void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
delegate_->UpdatePreferredSize(this, new_size);
}
-WebUI* WebContentsImpl::CreateWebUI(const GURL& url,
- const std::string& frame_name) {
- WebUIImpl* web_ui = new WebUIImpl(this, frame_name);
- WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
- CreateWebUIControllerForURL(web_ui, url);
+std::unique_ptr<WebUIImpl> WebContentsImpl::CreateWebUI(
+ const GURL& url,
+ const std::string& frame_name) {
+ std::unique_ptr<WebUIImpl> web_ui =
+ base::MakeUnique<WebUIImpl>(this, frame_name);
+ WebUIController* controller =
+ WebUIControllerFactoryRegistry::GetInstance()
+ ->CreateWebUIControllerForURL(web_ui.get(), url);
if (controller) {
web_ui->AddMessageHandler(new GenericHandler());
web_ui->SetController(controller);
return web_ui;
}
- delete web_ui;
- return NULL;
+ return nullptr;
}
FindRequestManager* WebContentsImpl::GetOrCreateFindRequestManager() {
@@ -5218,13 +5253,27 @@ void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
}
void WebContentsImpl::MediaStartedPlaying(
+ const WebContentsObserver::MediaPlayerInfo& media_info,
const WebContentsObserver::MediaPlayerId& id) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, MediaStartedPlaying(id));
+ if (media_info.has_video)
+ currently_playing_video_count_++;
+
+ for (auto& observer : observers_)
+ observer.MediaStartedPlaying(media_info, id);
}
void WebContentsImpl::MediaStoppedPlaying(
+ const WebContentsObserver::MediaPlayerInfo& media_info,
const WebContentsObserver::MediaPlayerId& id) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, MediaStoppedPlaying(id));
+ if (media_info.has_video)
+ currently_playing_video_count_--;
+
+ for (auto& observer : observers_)
+ observer.MediaStoppedPlaying(media_info, id);
+}
+
+int WebContentsImpl::GetCurrentlyPlayingVideoCount() {
+ return currently_playing_video_count_;
}
void WebContentsImpl::UpdateWebContentsVisibility(bool visible) {
@@ -5277,4 +5326,19 @@ void WebContentsImpl::RemoveBindingSet(const std::string& interface_name) {
binding_sets_.erase(it);
}
+void WebContentsImpl::FocusedNodeTouched(bool editable) {
+#if defined(OS_WIN)
+ // We use the cursor position to determine where the touch occurred.
+ RenderWidgetHostView* view = GetRenderWidgetHostView();
+ if (!view)
+ return;
+ POINT cursor_pos = {};
+ ::GetCursorPos(&cursor_pos);
+ float scale = GetScaleFactorForView(view);
+ gfx::Point location_dips_screen =
+ gfx::ConvertPointToDIP(scale, gfx::Point(cursor_pos));
+ view->FocusedNodeTouched(location_dips_screen, editable);
+#endif
+}
+
} // 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 f6df8a0bc93..17321a139a0 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -51,7 +51,7 @@
struct ViewHostMsg_DateTimeDialogValue_Params;
-namespace shell {
+namespace service_manager {
class InterfaceProvider;
}
@@ -59,15 +59,14 @@ namespace content {
class BrowserPluginEmbedder;
class BrowserPluginGuest;
class DateTimeChooserAndroid;
-class DownloadItem;
class FindRequestManager;
+class HostZoomMapObserver;
class InterstitialPageImpl;
class JavaScriptDialogManager;
class LoaderIOThreadNotifier;
class ManifestManagerHost;
class MediaWebContentsObserver;
class PluginContentOriginWhitelist;
-class PowerSaveBlocker;
class RenderViewHost;
class RenderViewHostDelegateView;
class RenderWidgetHostImpl;
@@ -182,13 +181,14 @@ class CONTENT_EXPORT WebContentsImpl
// plugins it is hosting.
void CancelActiveAndPendingDialogs();
- // Invoked when visible SSL state (as defined by SSLStatus) changes.
- void DidChangeVisibleSSLState();
-
// Informs the render view host and the BrowserPluginEmbedder, if present, of
// a Drag Source End.
- void DragSourceEndedAt(int client_x, int client_y, int screen_x,
- int screen_y, blink::WebDragOperation operation);
+ void DragSourceEndedAt(int client_x,
+ int client_y,
+ int screen_x,
+ int screen_y,
+ blink::WebDragOperation operation,
+ RenderWidgetHost* source_rwh);
// Notification that the RenderViewHost's load state changed.
void LoadStateChanged(const GURL& url,
@@ -290,8 +290,9 @@ class CONTENT_EXPORT WebContentsImpl
void ClosePage() override;
RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const override;
SkColor GetThemeColor() const override;
- WebUI* CreateSubframeWebUI(const GURL& url,
- const std::string& frame_name) override;
+ std::unique_ptr<WebUI> CreateSubframeWebUI(
+ const GURL& url,
+ const std::string& frame_name) override;
WebUI* GetWebUI() const override;
WebUI* GetCommittedWebUI() const override;
void SetUserAgentOverride(const std::string& override) override;
@@ -303,8 +304,6 @@ class CONTENT_EXPORT WebContentsImpl
const base::string16& GetTitle() const override;
void UpdateTitleForEntry(NavigationEntry* entry,
const base::string16& title) override;
- int32_t GetMaxPageID() override;
- int32_t GetMaxPageIDForSiteInstance(SiteInstance* site_instance) override;
SiteInstanceImpl* GetSiteInstance() const override;
SiteInstanceImpl* GetPendingSiteInstance() const override;
bool IsLoading() const override;
@@ -327,8 +326,10 @@ class CONTENT_EXPORT WebContentsImpl
int GetCrashedErrorCode() const override;
bool IsBeingDestroyed() const override;
void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
+ void OnAudioStateChanged(bool is_audible) override;
base::TimeTicks GetLastActiveTime() const override;
void SetLastActiveTime(base::TimeTicks last_active_time) override;
+ base::TimeTicks GetLastHiddenTime() const override;
void WasShown() override;
void WasHidden() override;
bool NeedToFireBeforeUnload() override;
@@ -336,6 +337,7 @@ class CONTENT_EXPORT WebContentsImpl
void AttachToOuterWebContentsFrame(
WebContents* outer_web_contents,
RenderFrameHost* outer_contents_frame) override;
+ void DidChangeVisibleSecurityState() override;
void Stop() override;
WebContents* Clone() override;
void ReloadFocusedFrame(bool bypass_cache) override;
@@ -385,7 +387,7 @@ class CONTENT_EXPORT WebContentsImpl
bool WillNotifyDisconnection() const override;
RendererPreferences* GetMutableRendererPrefs() override;
void Close() override;
- void SystemDragEnded() override;
+ void SystemDragEnded(RenderWidgetHost* source_rwh) override;
void UserGestureDone() override;
void SetClosedByUserGesture(bool value) override;
bool GetClosedByUserGesture() const override;
@@ -414,30 +416,22 @@ class CONTENT_EXPORT WebContentsImpl
void GetManifest(const GetManifestCallback& callback) override;
void ExitFullscreen(bool will_cause_resize) override;
void ResumeLoadingCreatedWebContents() override;
- void OnMediaSessionStateChanged();
- void ResumeMediaSession() override;
- void SuspendMediaSession() override;
- void StopMediaSession() override;
+ void OnPasswordInputShownOnHttp() override;
+ void OnAllPasswordInputsHiddenOnHttp() override;
+ void OnCreditCardInputShownOnHttp() override;
+ void SetIsOverlayContent(bool is_overlay_content) override;
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
virtual WebContentsAndroid* GetWebContentsAndroid();
void ActivateNearestFindResult(float x, float y) override;
void RequestFindMatchRects(int current_version) override;
- shell::InterfaceProvider* GetJavaInterfaces() override;
+ service_manager::InterfaceProvider* GetJavaInterfaces() override;
#elif defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) override;
bool GetAllowOtherViews() override;
#endif
- // Returns true if this is a secure page which has displayed content
- // loaded over insecure HTTP.
- bool DisplayedInsecureContent() const;
-
- // Returns true if this page has displayed content loaded over HTTPS
- // with certificate errors.
- bool DisplayedContentWithCertErrors() const;
-
// Implementation of PageNavigator.
WebContents* OpenURL(const OpenURLParams& params) override;
@@ -474,7 +468,6 @@ class CONTENT_EXPORT WebContentsImpl
void UpdateStateForFrame(RenderFrameHost* render_frame_host,
const PageState& page_state) override;
void UpdateTitle(RenderFrameHost* render_frame_host,
- int32_t page_id,
const base::string16& title,
base::i18n::TextDirection title_direction) override;
void UpdateEncoding(RenderFrameHost* render_frame_host,
@@ -490,7 +483,7 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHost* render_frame_host,
int browser_plugin_instance_id) override;
device::GeolocationServiceContext* GetGeolocationServiceContext() override;
- WakeLockServiceContext* GetWakeLockServiceContext() override;
+ device::WakeLockServiceContext* GetWakeLockServiceContext() override;
void EnterFullscreenMode(const GURL& origin) override;
void ExitFullscreenMode(bool will_cause_resize) override;
bool ShouldRouteMessageEvent(
@@ -500,6 +493,9 @@ class CONTENT_EXPORT WebContentsImpl
std::unique_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(
const GURL& url) override;
void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override;
+ void OnFocusedElementChangedInFrame(
+ RenderFrameHostImpl* frame,
+ const gfx::Rect& bounds_in_root_view) override;
// RenderViewHostDelegate ----------------------------------------------------
RenderViewHostDelegateView* GetDelegateView() override;
@@ -515,7 +511,6 @@ class CONTENT_EXPORT WebContentsImpl
int error_code) override;
void RenderViewDeleted(RenderViewHost* render_view_host) override;
void UpdateState(RenderViewHost* render_view_host,
- int32_t page_id,
const PageState& page_state) override;
void UpdateTargetURL(RenderViewHost* render_view_host,
const GURL& url) override;
@@ -524,10 +519,10 @@ class CONTENT_EXPORT WebContentsImpl
void DidCancelLoading() override;
void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) override;
void RouteCloseEvent(RenderViewHost* rvh) override;
- bool AddMessageToConsole(int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override;
+ bool DidAddMessageToConsole(int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override;
RendererPreferences GetRendererPrefs(
BrowserContext* browser_context) const override;
void OnUserInteraction(RenderWidgetHostImpl* render_widget_host,
@@ -564,11 +559,15 @@ class CONTENT_EXPORT WebContentsImpl
SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) override;
SessionStorageNamespaceMap GetSessionStorageNamespaceMap() override;
+ double GetPendingPageZoomLevel() override;
FrameTree* GetFrameTree() override;
void SetIsVirtualKeyboardRequested(bool requested) override;
bool IsVirtualKeyboardRequested() override;
bool IsOverridingUserAgent() override;
- double GetPendingPageZoomLevel() override;
+ bool IsJavaScriptDialogShowing() const override;
+ bool HideDownloadUI() const override;
+ bool IsFocusedElementEditable() override;
+ void ClearFocusedElement() override;
// NavigatorDelegate ---------------------------------------------------------
@@ -653,16 +652,16 @@ class CONTENT_EXPORT WebContentsImpl
void ReplicatePageFocus(bool is_focused) override;
RenderWidgetHostImpl* GetFocusedRenderWidgetHost(
RenderWidgetHostImpl* receiving_widget) override;
- void RendererUnresponsive(
- RenderWidgetHostImpl* render_widget_host,
- RenderWidgetHostDelegate::RendererUnresponsiveType type) override;
+ RenderWidgetHostImpl* GetRenderWidgetHostWithPageFocus() override;
+ void FocusOwningWebContents(
+ RenderWidgetHostImpl* render_widget_host) override;
+ void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host,
+ RendererUnresponsiveType type) override;
void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override;
void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
bool last_unlocked_by_target,
bool privileged) override;
- gfx::Rect GetRootWindowResizerRect(
- RenderWidgetHostImpl* render_widget_host) const override;
bool IsFullscreenForCurrentTab() const override;
blink::WebDisplayMode GetDisplayMode(
RenderWidgetHostImpl* render_widget_host) const override;
@@ -675,6 +674,8 @@ class CONTENT_EXPORT WebContentsImpl
void SendScreenRects() override;
void OnFirstPaintAfterLoad(RenderWidgetHostImpl* render_widget_host) override;
TextInputManager* GetTextInputManager() override;
+ bool OnUpdateDragCursor() override;
+ void FocusedNodeTouched(bool editable) override;
// RenderFrameHostManager::Delegate ------------------------------------------
@@ -736,20 +737,6 @@ class CONTENT_EXPORT WebContentsImpl
// first commit.
bool HasAccessedInitialDocument() override;
- // Updates the max page ID for the current SiteInstance in this
- // WebContentsImpl to be at least |page_id|.
- void UpdateMaxPageID(int32_t page_id) override;
-
- // Updates the max page ID for the given SiteInstance in this WebContentsImpl
- // to be at least |page_id|.
- void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
- int32_t page_id) override;
-
- // Copy the current map of SiteInstance ID to max page ID from another tab.
- // This is necessary when this tab adopts the NavigationEntries from
- // |web_contents|.
- void CopyMaxPageIDsFrom(WebContents* web_contents) override;
-
// Sets the history for this WebContentsImpl to |history_length| entries, with
// an offset of |history_offset|. This notifies all renderers involved in
// rendering the current page about the new offset and length.
@@ -783,8 +770,15 @@ class CONTENT_EXPORT WebContentsImpl
// Called by MediaWebContentsObserver when playback starts or stops. See the
// WebContentsObserver function stubs for more details.
- void MediaStartedPlaying(const WebContentsObserver::MediaPlayerId& id);
- void MediaStoppedPlaying(const WebContentsObserver::MediaPlayerId& id);
+ void MediaStartedPlaying(
+ const WebContentsObserver::MediaPlayerInfo& media_info,
+ const WebContentsObserver::MediaPlayerId& id);
+ void MediaStoppedPlaying(
+ const WebContentsObserver::MediaPlayerInfo& media_info,
+ const WebContentsObserver::MediaPlayerId& id);
+ int GetCurrentlyPlayingVideoCount() override;
+
+ bool IsFullscreen() override;
MediaWebContentsObserver* media_web_contents_observer() {
return media_web_contents_observer_.get();
@@ -1025,12 +1019,35 @@ class CONTENT_EXPORT WebContentsImpl
// up at the next animation step if the throbber is going.
void SetNotWaitingForResponse() { waiting_for_response_ = false; }
+ // Inner WebContents Helpers -------------------------------------------------
+ //
+ // These functions are helpers in managing a hierarchy of WebContents
+ // involved in rendering inner WebContents.
+
+ // When multiple WebContents are present within a tab or window, a single one
+ // is focused and will route keyboard events in most cases to a RenderWidget
+ // contained within it. |GetFocusedWebContents()|'s main frame widget will
+ // receive page focus and blur events when the containing window changes focus
+ // state.
+
// Returns the focused WebContents.
// If there are multiple inner/outer WebContents (when embedding <webview>,
// <guestview>, ...) returns the single one containing the currently focused
// frame. Otherwise, returns this WebContents.
WebContentsImpl* GetFocusedWebContents();
+ // Returns true if |this| is the focused WebContents or an ancestor of the
+ // focused WebContents.
+ bool ContainsOrIsFocusedWebContents();
+
+ // When inner or outer WebContents are present, become the focused
+ // WebContentsImpl. This will activate this content's main frame RenderWidget
+ // and indirectly all its subframe widgets. GetFocusedRenderWidgetHost will
+ // search this WebContentsImpl for a focused RenderWidgetHost. The previously
+ // focused WebContentsImpl, if any, will have its RenderWidgetHosts
+ // deactivated.
+ void SetAsFocusedWebContentsIfNecessary();
+
// Returns the root of the WebContents tree.
WebContentsImpl* GetOutermostWebContents();
@@ -1043,12 +1060,6 @@ class CONTENT_EXPORT WebContentsImpl
// not provided since it may be invalid/changed after being committed. The
// current navigation entry is in the NavigationController at this point.
- // If our controller was restored, update the max page ID associated with the
- // given RenderViewHost to be larger than the number of restored entries.
- // This is called in CreateRenderView before any navigations in the RenderView
- // have begun, to prevent any races in updating RenderView::next_page_id.
- void UpdateMaxPageIDIfNecessary(RenderViewHost* rvh);
-
// Helper for CreateNewWidget/CreateNewFullscreenWidget.
void CreateNewWidget(int32_t render_process_id,
int32_t route_id,
@@ -1126,7 +1137,8 @@ class CONTENT_EXPORT WebContentsImpl
// used to determine which WebUI should be created (if any). |frame_name|
// corresponds to the name of a frame that the WebUI should be created for (or
// the main frame if empty).
- WebUI* CreateWebUI(const GURL& url, const std::string& frame_name);
+ std::unique_ptr<WebUIImpl> CreateWebUI(const GURL& url,
+ const std::string& frame_name);
void SetJavaScriptDialogManagerForTesting(
JavaScriptDialogManager* dialog_manager);
@@ -1208,11 +1220,6 @@ class CONTENT_EXPORT WebContentsImpl
// "waiting" or "loading."
bool waiting_for_response_;
- // Map of SiteInstance ID to max page ID for this tab. A page ID is specific
- // to a given tab and SiteInstance, and must be valid for the lifetime of the
- // WebContentsImpl.
- std::map<int32_t, int32_t> max_page_ids_;
-
// The current load state and the URL associated with it.
net::LoadStateWithParam load_state_;
base::string16 load_state_host_;
@@ -1243,14 +1250,6 @@ class CONTENT_EXPORT WebContentsImpl
// The canonicalized character encoding.
std::string canonical_encoding_;
- // True if this is a secure page which displayed mixed content (loaded
- // over HTTP).
- bool displayed_insecure_content_;
-
- // True if this page displayed subresources loaded with HTTPS
- // certificate errors.
- bool displayed_content_with_cert_errors_;
-
// Whether the initial empty page has been accessed by another page, making it
// unsafe to show the pending URL. Usually false unless another window tries
// to modify the blank page. Always false after the first commit.
@@ -1295,6 +1294,9 @@ class CONTENT_EXPORT WebContentsImpl
// delegate of this WebContentsImpl is nulled before its destructor is called.
JavaScriptDialogManager* dialog_manager_;
+ // Set to true when there is an active JavaScript dialog showing.
+ bool is_showing_javascript_dialog_ = false;
+
// Set to true when there is an active "before unload" dialog. When true,
// we've forced the throbber to start in Navigate, and we need to remember to
// turn it off in OnJavaScriptMessageBoxClosed if the navigation is canceled.
@@ -1307,6 +1309,10 @@ class CONTENT_EXPORT WebContentsImpl
// the WebContents creation time.
base::TimeTicks last_active_time_;
+ // The time that this WebContents was last made hidden. The initial value is
+ // zero.
+ base::TimeTicks last_hidden_time_;
+
// See description above setter.
bool closed_by_user_gesture_;
@@ -1413,7 +1419,7 @@ class CONTENT_EXPORT WebContentsImpl
std::unique_ptr<device::GeolocationServiceContext>
geolocation_service_context_;
- std::unique_ptr<WakeLockServiceContext> wake_lock_service_context_;
+ std::unique_ptr<device::WakeLockServiceContext> wake_lock_service_context_;
std::unique_ptr<ScreenOrientationDispatcherHost>
screen_orientation_dispatcher_host_;
@@ -1445,6 +1451,8 @@ class CONTENT_EXPORT WebContentsImpl
std::unique_ptr<PepperPlaybackObserver> pepper_playback_observer_;
#endif // defined(ENABLE_PLUGINS)
+ std::unique_ptr<HostZoomMapObserver> host_zoom_map_observer_;
+
std::unique_ptr<RenderWidgetHostInputEventRouter> rwh_input_event_router_;
PageImportanceSignals page_importance_signals_;
@@ -1464,9 +1472,14 @@ class CONTENT_EXPORT WebContentsImpl
RenderWidgetHostImpl* mouse_lock_widget_;
#if defined(OS_ANDROID)
- std::unique_ptr<shell::InterfaceProvider> java_interfaces_;
+ std::unique_ptr<service_manager::InterfaceProvider> java_interfaces_;
#endif
+ // Whether this WebContents is for content overlay.
+ bool is_overlay_content_;
+
+ int currently_playing_video_count_ = 0;
+
base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
base::WeakPtrFactory<WebContentsImpl> weak_factory_;
diff --git a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
index 21113083f7e..28a1ab37940 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -899,17 +899,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
// TODO(clamy): Make the test work on Windows and on Mac. On Mac and Windows,
// there seem to be an issue with the ShellJavascriptDialogManager.
-#if defined(OS_WIN) || defined(OS_MACOSX)
-#define MAYBE_NoResetOnBeforeUnloadCanceledOnCommit \
- DISABLED_NoResetOnBeforeUnloadCanceledOnCommit
-#else
-#define MAYBE_NoResetOnBeforeUnloadCanceledOnCommit \
- NoResetOnBeforeUnloadCanceledOnCommit
-#endif
+// Flaky on all platforms: https://crbug.com/655628
// Test that if a BeforeUnload dialog is destroyed due to the commit of a
// cross-site navigation, it will not reset the loading state.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- MAYBE_NoResetOnBeforeUnloadCanceledOnCommit) {
+ DISABLED_NoResetOnBeforeUnloadCanceledOnCommit) {
ASSERT_TRUE(embedded_test_server()->Start());
const GURL kStartURL(
embedded_test_server()->GetURL("/hang_before_unload.html"));
@@ -923,7 +917,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
TestNavigationManager cross_site_delayer(shell()->web_contents(),
kCrossSiteURL);
shell()->LoadURL(kCrossSiteURL);
- EXPECT_TRUE(cross_site_delayer.WaitForWillStartRequest());
+ EXPECT_TRUE(cross_site_delayer.WaitForRequestStart());
// Click on a link in the page. This will show the BeforeUnload dialog.
// Ensure the dialog is not dismissed, which will cause it to still be
@@ -989,9 +983,9 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
return true;
}
- void CancelActiveAndPendingDialogs(WebContents* web_contents) override {}
-
- void ResetDialogState(WebContents* web_contents) override {}
+ void CancelDialogs(WebContents* web_contents,
+ bool suppress_callbacks,
+ bool reset_state) override {}
private:
std::string last_message_;
@@ -1250,4 +1244,64 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_NoValidImage) {
run_loop.Run();
}
+class MouseLockDelegate : public WebContentsDelegate {
+ public:
+ // WebContentsDelegate:
+ void RequestToLockMouse(WebContents* web_contents,
+ bool user_gesture,
+ bool last_unlocked_by_target) override {
+ request_to_lock_mouse_called_ = true;
+ }
+ bool request_to_lock_mouse_called_ = false;
+};
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ RenderWidgetDeletedWhileMouseLockPending) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ std::unique_ptr<MouseLockDelegate> delegate(new MouseLockDelegate());
+ shell()->web_contents()->SetDelegate(delegate.get());
+ ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
+
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("a.com", "/title1.html"));
+
+ // Try to request pointer lock. WebContentsDelegate should get a notification.
+ ASSERT_TRUE(ExecuteScript(shell(),
+ "window.domAutomationController.send(document.body."
+ "requestPointerLock());"));
+ EXPECT_TRUE(delegate.get()->request_to_lock_mouse_called_);
+
+ // Make sure that the renderer didn't get the pointer lock, since the
+ // WebContentsDelegate didn't approve the notification.
+ bool locked = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(shell(),
+ "window.domAutomationController.send("
+ "document.pointerLockElement == "
+ "null);",
+ &locked));
+ EXPECT_TRUE(locked);
+
+ // Try to request the pointer lock again. Since there's a pending request in
+ // WebContentsDelelgate, the WebContents shouldn't ask again.
+ delegate.get()->request_to_lock_mouse_called_ = false;
+ ASSERT_TRUE(ExecuteScript(shell(),
+ "window.domAutomationController.send(document.body."
+ "requestPointerLock());"));
+ EXPECT_FALSE(delegate.get()->request_to_lock_mouse_called_);
+
+ // Force a cross-process navigation so that the RenderWidgetHost is deleted.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+ // Make sure the WebContents cleaned up the previous pending request. A new
+ // request should be forwarded to the WebContentsDelegate.
+ delegate.get()->request_to_lock_mouse_called_ = false;
+ ASSERT_TRUE(ExecuteScript(shell(),
+ "window.domAutomationController.send(document.body."
+ "requestPointerLock());"));
+ EXPECT_TRUE(delegate.get()->request_to_lock_mouse_called_);
+}
+
} // namespace content
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 3bb66634144..d2aee22f5a5 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -24,7 +23,6 @@
#include "content/common/frame_messages.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/media/media_player_delegate_messages.h"
-#include "content/common/security_style_util.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -146,12 +144,11 @@ class TestInterstitialPage : public InterstitialPageImpl {
CommandReceived();
}
- void TestDidNavigate(int page_id,
- int nav_entry_id,
+ void TestDidNavigate(int nav_entry_id,
bool did_create_new_entry,
const GURL& url) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, page_id, nav_entry_id, did_create_new_entry,
+ InitNavigateParams(&params, nav_entry_id, did_create_new_entry,
url, ui::PAGE_TRANSITION_TYPED);
DidNavigate(GetMainFrame()->GetRenderViewHost(), params);
}
@@ -364,12 +361,12 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, 0, 0, true, GURL(url::kAboutBlankURL),
+ InitNavigateParams(&params, 0, true, GURL(url::kAboutBlankURL),
ui::PAGE_TRANSITION_TYPED);
main_test_rfh()->SendNavigateWithParams(&params);
- contents()->UpdateTitle(main_test_rfh(), 0,
+ contents()->UpdateTitle(main_test_rfh(),
base::ASCIIToUTF16(" Lots O' Whitespace\n"),
base::i18n::LEFT_TO_RIGHT);
EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
@@ -378,8 +375,7 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) {
ASSERT_TRUE(controller().IsInitialNavigation());
const base::string16 title = base::ASCIIToUTF16("Initial Entry Title");
- contents()->UpdateTitle(main_test_rfh(), -1, title,
- base::i18n::LEFT_TO_RIGHT);
+ contents()->UpdateTitle(main_test_rfh(), title, base::i18n::LEFT_TO_RIGHT);
EXPECT_EQ(title, contents()->GetTitle());
}
@@ -391,8 +387,7 @@ TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
// Also test setting title while the first navigation is still pending.
const base::string16 title = base::ASCIIToUTF16("Initial Entry Title");
- contents()->UpdateTitle(main_test_rfh(), -1, title,
- base::i18n::LEFT_TO_RIGHT);
+ contents()->UpdateTitle(main_test_rfh(), title, base::i18n::LEFT_TO_RIGHT);
EXPECT_EQ(title, contents()->GetTitle());
}
@@ -434,7 +429,7 @@ TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
FrameMsg_EnableViewSourceMode::ID));
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, 0, entry_id, true, kRewrittenURL,
+ InitNavigateParams(&params, entry_id, true, kRewrittenURL,
ui::PAGE_TRANSITION_TYPED);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->OnMessageReceived(
@@ -451,29 +446,6 @@ TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
contents()->GetController().GetLastCommittedEntry()->GetURL());
}
-// Test to ensure UpdateMaxPageID is working properly.
-TEST_F(WebContentsImplTest, UpdateMaxPageID) {
- SiteInstance* instance1 = contents()->GetSiteInstance();
- scoped_refptr<SiteInstance> instance2(SiteInstance::Create(nullptr));
-
- // Starts at -1.
- EXPECT_EQ(-1, contents()->GetMaxPageID());
- EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance1));
- EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2.get()));
-
- // Make sure max_page_id_ is monotonically increasing per SiteInstance.
- contents()->UpdateMaxPageID(3);
- contents()->UpdateMaxPageID(1);
- EXPECT_EQ(3, contents()->GetMaxPageID());
- EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1));
- EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2.get()));
-
- contents()->UpdateMaxPageIDForSiteInstance(instance2.get(), 7);
- EXPECT_EQ(3, contents()->GetMaxPageID());
- EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1));
- EXPECT_EQ(7, contents()->GetMaxPageIDForSiteInstance(instance2.get()));
-}
-
// Test simple same-SiteInstance navigation.
TEST_F(WebContentsImplTest, SimpleNavigation) {
TestRenderFrameHost* orig_rfh = main_test_rfh();
@@ -496,7 +468,7 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
site_instance());
// DidNavigate from the page
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -548,7 +520,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Keep the number of active frames in orig_rfh's SiteInstance non-zero so
@@ -584,7 +556,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
}
// DidNavigate from the pending page
- contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
@@ -622,7 +594,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
}
// DidNavigate from the back action
- contents()->TestDidNavigate(goback_rfh, 1, entry_id, false, url2,
+ contents()->TestDidNavigate(goback_rfh, entry_id, false, url2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(goback_rfh, main_test_rfh());
@@ -654,7 +626,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -678,7 +650,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
EXPECT_EQ(orig_rvh_delete_count, 1);
// DidNavigate from the new page
- contents()->TestDidNavigate(new_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(new_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
@@ -705,7 +677,7 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Open a new contents with the same SiteInstance, navigated to the same site.
@@ -718,7 +690,7 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
contents2->GetMainFrame()->PrepareForCommit();
// Need this page id to be 2 since the site instance is the same (which is the
// scope of page IDs) and we want to consider this a new page.
- contents2->TestDidNavigate(contents2->GetMainFrame(), 2, entry_id, true, url,
+ contents2->TestDidNavigate(contents2->GetMainFrame(), entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Navigate first contents to a new site.
@@ -728,7 +700,7 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
- contents()->TestDidNavigate(pending_rfh_a, 1, entry_id, true, url2a,
+ contents()->TestDidNavigate(pending_rfh_a, entry_id, true, url2a,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2a = contents()->GetSiteInstance();
EXPECT_NE(instance1, instance2a);
@@ -748,7 +720,7 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
// NOTE(creis): We used to be in danger of showing a crash page here if the
// second contents hadn't navigated somewhere first (bug 1145430). That case
// is now covered by the CrossSiteBoundariesAfterCrash test.
- contents2->TestDidNavigate(pending_rfh_b, 2, entry_id, true, url2b,
+ contents2->TestDidNavigate(pending_rfh_b, entry_id, true, url2b,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2b = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2b);
@@ -777,7 +749,7 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, native_url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, native_url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -799,7 +771,7 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
EXPECT_EQ(url, contents()->GetVisibleURL());
EXPECT_FALSE(contents()->GetPendingMainFrame());
- contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Keep the number of active frames in orig_rfh's SiteInstance
@@ -835,7 +807,7 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
}
// DidNavigate from the pending page.
- contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* new_instance = contents()->GetSiteInstance();
@@ -875,7 +847,6 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
NavigationControllerImpl::CreateNavigationEntry(
native_url, Referrer(), ui::PAGE_TRANSITION_LINK, false,
std::string(), browser_context());
- new_entry->SetPageID(0);
entries.push_back(std::move(new_entry));
controller().Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -884,7 +855,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
controller().GoToIndex(0);
NavigationEntry* entry = controller().GetPendingEntry();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false,
+ contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), false,
native_url, ui::PAGE_TRANSITION_RELOAD);
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
EXPECT_EQ(GURL(), contents()->GetSiteInstance()->GetSiteURL());
@@ -897,7 +868,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry = controller().GetPendingEntry();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, url,
+ contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
@@ -922,7 +893,6 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
NavigationControllerImpl::CreateNavigationEntry(
regular_url, Referrer(), ui::PAGE_TRANSITION_LINK, false,
std::string(), browser_context());
- new_entry->SetPageID(0);
entries.push_back(std::move(new_entry));
controller().Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -931,7 +901,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
controller().GoToIndex(0);
NavigationEntry* entry = controller().GetPendingEntry();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false,
+ contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), false,
regular_url, ui::PAGE_TRANSITION_RELOAD);
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
EXPECT_TRUE(orig_instance->HasSite());
@@ -942,7 +912,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry = controller().GetPendingEntry();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetPendingMainFrame(), 2,
+ contents()->TestDidNavigate(contents()->GetPendingMainFrame(),
entry->GetUniqueID(), true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_NE(orig_instance, contents()->GetSiteInstance());
@@ -962,7 +932,7 @@ TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Start to navigate first tab to a new site, so that it has a pending RVH.
@@ -993,7 +963,7 @@ TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
// Ensure that committing the navigation removes the proxy.
entry_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->TestDidNavigate(pending_rfh, 2, entry_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(
contents()->GetRenderManager()->GetRenderFrameProxyHost(instance));
@@ -1011,7 +981,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
// Open a related contents to a second site.
@@ -1028,7 +998,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// pending.
TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
EXPECT_FALSE(contents2->CrossProcessNavigationPending());
- contents2->TestDidNavigate(rfh2, 2, entry_id, true, url2,
+ contents2->TestDidNavigate(rfh2, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2);
@@ -1038,7 +1008,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// SiteInstances, because we don't intercept Blink navigations.
orig_rfh->SendRendererInitiatedNavigationRequest(url2, true);
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 2, 0, true, url2,
+ contents()->TestDidNavigate(orig_rfh, 0, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance3 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance3);
@@ -1052,7 +1022,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 3, entry_id, true, url3,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url3,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance4 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance4);
@@ -1070,7 +1040,7 @@ TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1101,7 +1071,7 @@ TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
// We won't hear DidNavigate until the onunload handler has finished running.
// DidNavigate from the pending page.
- contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -1123,7 +1093,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationPreempted) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1137,7 +1107,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationPreempted) {
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
// Suppose the original renderer navigates before the new one is ready.
- orig_rfh->SendNavigate(2, 0, true, GURL("http://www.google.com/foo"));
+ orig_rfh->SendNavigate(0, true, GURL("http://www.google.com/foo"));
// Verify that the pending navigation is cancelled.
EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
@@ -1161,7 +1131,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
TestRenderFrameHost* webui_rfh = main_test_rfh();
webui_rfh->PrepareForCommit();
- contents()->TestDidNavigate(webui_rfh, 1, entry_id, true, url1,
+ contents()->TestDidNavigate(webui_rfh, entry_id, true, url1,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry1 = controller().GetLastCommittedEntry();
SiteInstance* instance1 = contents()->GetSiteInstance();
@@ -1187,7 +1157,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
webui_rfh->PrepareForCommit();
// DidNavigate from the pending page.
- contents()->TestDidNavigate(google_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(google_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry2 = controller().GetLastCommittedEntry();
SiteInstance* instance2 = contents()->GetSiteInstance();
@@ -1209,7 +1179,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(google_rfh, 2, entry_id, true, url3,
+ contents()->TestDidNavigate(google_rfh, entry_id, true, url3,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry3 = controller().GetLastCommittedEntry();
SiteInstance* instance3 = contents()->GetSiteInstance();
@@ -1242,7 +1212,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
// DidNavigate from the first back. This aborts the second back's pending RFH.
- contents()->TestDidNavigate(google_rfh, 1, goback_entry->GetUniqueID(), false,
+ contents()->TestDidNavigate(google_rfh, goback_entry->GetUniqueID(), false,
url2, ui::PAGE_TRANSITION_TYPED);
// We should commit this page and forget about the second back.
@@ -1272,7 +1242,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
TestRenderFrameHost* webui_rfh = main_test_rfh();
webui_rfh->PrepareForCommit();
- contents()->TestDidNavigate(webui_rfh, 1, entry_id, true, url1,
+ contents()->TestDidNavigate(webui_rfh, entry_id, true, url1,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry1 = controller().GetLastCommittedEntry();
SiteInstance* instance1 = contents()->GetSiteInstance();
@@ -1298,7 +1268,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
webui_rfh->PrepareForCommit();
// DidNavigate from the pending page.
- contents()->TestDidNavigate(google_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(google_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry2 = controller().GetLastCommittedEntry();
SiteInstance* instance2 = contents()->GetSiteInstance();
@@ -1320,7 +1290,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(google_rfh, 2, entry_id, true, url3,
+ contents()->TestDidNavigate(google_rfh, entry_id, true, url3,
ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry3 = controller().GetLastCommittedEntry();
SiteInstance* instance3 = contents()->GetSiteInstance();
@@ -1346,14 +1316,14 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
webui_rfh = contents()->GetPendingMainFrame();
// DidNavigate from the second back.
- contents()->TestDidNavigate(webui_rfh, 1, entry1->GetUniqueID(), false, url1,
+ contents()->TestDidNavigate(webui_rfh, entry1->GetUniqueID(), false, url1,
ui::PAGE_TRANSITION_TYPED);
// That should have landed us on the first entry.
EXPECT_EQ(entry1, controller().GetLastCommittedEntry());
// When the second back commits, it should be ignored.
- contents()->TestDidNavigate(google_rfh, 1, entry2->GetUniqueID(), false, url2,
+ contents()->TestDidNavigate(google_rfh, entry2->GetUniqueID(), false, url2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(entry1, controller().GetLastCommittedEntry());
}
@@ -1369,7 +1339,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationNotPreemptedByFrame) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1382,7 +1352,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationNotPreemptedByFrame) {
// Simulate a sub-frame navigation arriving and ensure the RVH is still
// waiting for a before unload response.
TestRenderFrameHost* child_rfh = orig_rfh->AppendChild("subframe");
- child_rfh->SendNavigateWithTransition(1, 0, false,
+ child_rfh->SendNavigateWithTransition(0, false,
GURL("http://google.com/frame"),
ui::PAGE_TRANSITION_AUTO_SUBFRAME);
EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
@@ -1428,7 +1398,7 @@ TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
// FrameMsg_Stop in flight. This should not cancel the pending navigation,
// but it should act as if the beforeunload ack arrived.
orig_rfh->SendNavigateWithModificationCallback(
- 1, entry1_id, true, url, base::Bind(SetAsNonUserGesture));
+ entry1_id, true, url, base::Bind(SetAsNonUserGesture));
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
@@ -1437,7 +1407,7 @@ TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
EXPECT_EQ(url, controller().GetLastCommittedEntry()->GetURL());
// The pending navigation should be able to commit successfully.
- contents()->TestDidNavigate(pending_rfh, 1, entry2_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry2_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(pending_rfh, main_test_rfh());
@@ -1459,7 +1429,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentState) {
// Committed entry should have page state after DidNavigate.
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
@@ -1474,7 +1444,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentState) {
// Committed entry should have page state after DidNavigate.
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
@@ -1483,7 +1453,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentState) {
controller().GoBack();
entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, false, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, false, url,
ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
@@ -1498,7 +1468,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
// Navigate to about:blank.
const GURL url(url::kAboutBlankURL);
orig_rfh->SendRendererInitiatedNavigationRequest(url, false);
- contents()->TestDidNavigate(orig_rfh, 1, 0, true, url,
+ contents()->TestDidNavigate(orig_rfh, 0, true, url,
ui::PAGE_TRANSITION_TYPED);
// Should have a page state here.
@@ -1519,7 +1489,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, new_url,
+ contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, new_url,
ui::PAGE_TRANSITION_TYPED);
NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry(
controller().GetLastCommittedEntry());
@@ -1540,7 +1510,7 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1559,7 +1529,7 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame();
- contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
// Confirm fullscreen has exited.
@@ -1582,7 +1552,7 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1593,7 +1563,7 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1617,7 +1587,7 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
orig_rfh->PrepareForCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
- contents()->TestDidNavigate(orig_rfh, i + 1, entry_id, false, url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, false, url,
ui::PAGE_TRANSITION_FORWARD_BACK);
orig_rfh->SimulateNavigationStop();
@@ -1657,7 +1627,7 @@ TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(main_test_rfh(), 1, entry_id, true,
+ contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
url, ui::PAGE_TRANSITION_TYPED);
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
@@ -1689,7 +1659,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial.
@@ -1712,7 +1682,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -1741,7 +1711,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromRendererWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial (no pending entry, the interstitial would have been
@@ -1760,7 +1730,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -1788,7 +1758,7 @@ TEST_F(WebContentsImplTest,
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1805,7 +1775,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, 0, true, url2);
+ interstitial->TestDidNavigate(0, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -1835,7 +1805,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -1857,7 +1827,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -1878,7 +1848,7 @@ TEST_F(WebContentsImplTest,
// hidden.
GURL url3("http://www.thepage.com");
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(2, 0, true, url3);
+ main_test_rfh()->SendNavigate(0, true, url3);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
@@ -1899,7 +1869,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromRendererNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1917,7 +1887,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -1937,7 +1907,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(2, true, url3);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url3);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
@@ -1957,7 +1927,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(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1974,7 +1944,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
// Let's commit the interstitial navigation.
- interstitial->TestDidNavigate(1, 0, true, url2);
+ interstitial->TestDidNavigate(0, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
@@ -2012,11 +1982,11 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url);
// While interstitial showing, navigate to a new URL.
const GURL url2("http://www.yahoo.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -2028,7 +1998,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(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -2042,7 +2012,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(2, interstitial_entry_id, true,
+ interstitial->TestDidNavigate(interstitial_entry_id, true,
interstitial_url);
EXPECT_EQ(2, controller().GetEntryCount());
@@ -2068,7 +2038,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(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -2083,7 +2053,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(2, interstitial_entry_id, true,
+ interstitial->TestDidNavigate(interstitial_entry_id, true,
interstitial_url);
// Crash the renderer
@@ -2110,7 +2080,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(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -2128,7 +2098,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
// Crash the renderer
main_test_rfh()->GetProcess()->SimulateCrash();
- interstitial->TestDidNavigate(2, interstitial_entry_id, true,
+ interstitial->TestDidNavigate(interstitial_entry_id, true,
interstitial_url);
}
@@ -2145,7 +2115,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseTab) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url);
// Now close the contents.
DeleteContents();
@@ -2168,7 +2138,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url);
TestRenderFrameHost* rfh =
static_cast<TestRenderFrameHost*>(interstitial->GetMainFrame());
@@ -2190,7 +2160,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
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(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2203,7 +2173,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
// Run a command.
EXPECT_EQ(0, interstitial->command_received_count());
@@ -2226,7 +2196,7 @@ 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(1, true, start_url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2239,7 +2209,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
TestInterstitialPageStateGuard state_guard1(interstitial1);
interstitial1->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1);
+ interstitial1->TestDidNavigate(interstitial_entry_id, true, url1);
// Now show another interstitial.
TestInterstitialPage::InterstitialState state2 =
@@ -2251,7 +2221,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
TestInterstitialPageStateGuard state_guard2(interstitial2);
interstitial2->Show();
interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial2->TestDidNavigate(interstitial_entry_id, true, url2);
// Showing interstitial2 should have caused interstitial1 to go away.
EXPECT_EQ(TestInterstitialPage::CANCELED, state1);
@@ -2264,7 +2234,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com");
- main_test_rfh()->SendNavigate(2, 0, true, landing_url);
+ main_test_rfh()->SendNavigate(0, true, landing_url);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
@@ -2281,7 +2251,7 @@ 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(1, true, start_url);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2294,7 +2264,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
TestInterstitialPageStateGuard state_guard1(interstitial1);
interstitial1->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1);
+ interstitial1->TestDidNavigate(interstitial_entry_id, true, url1);
// Take action. The interstitial won't be hidden until the navigation is
// committed.
@@ -2312,7 +2282,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
TestInterstitialPageStateGuard state_guard2(interstitial2);
interstitial2->Show();
interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial2->TestDidNavigate(interstitial_entry_id, true, url2);
// Showing interstitial2 should have caused interstitial1 to go away.
EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2);
@@ -2323,7 +2293,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com");
- main_test_rfh()->SendNavigate(2, 0, true, landing_url);
+ main_test_rfh()->SendNavigate(0, true, landing_url);
RunAllPendingInMessageLoop();
EXPECT_TRUE(deleted2);
@@ -2360,7 +2330,7 @@ TEST_F(WebContentsImplTest, NavigateBeforeInterstitialShows) {
ASSERT_FALSE(deleted);
// Now let's make the interstitial navigation commit.
- interstitial->TestDidNavigate(1, interstitial_entry_id, true,
+ interstitial->TestDidNavigate(interstitial_entry_id, true,
interstitial_url);
// After it loaded the interstitial should be gone.
@@ -2407,7 +2377,7 @@ TEST_F(WebContentsImplTest, TwoQuickInterstitials) {
ASSERT_FALSE(deleted2);
// Make the interstitial navigation commit it should be showing.
- interstitial2->TestDidNavigate(1, interstitial_entry_id, true,
+ interstitial2->TestDidNavigate(interstitial_entry_id, true,
interstitial_url);
EXPECT_EQ(interstitial2, contents()->GetInterstitialPage());
}
@@ -2436,7 +2406,7 @@ TEST_F(WebContentsImplTest, InterstitialCrasher) {
new TestInterstitialPage(contents(), true, url, &state, &deleted);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url);
// Simulate a renderer crash.
interstitial->TestRenderViewTerminated(
base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
@@ -2466,7 +2436,7 @@ TEST_F(WebContentsImplTest, NewInterstitialDoesNotCancelPendingEntry) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, kGURL);
// Initiate a new navigation from the browser that also triggers an
// interstitial.
@@ -2480,7 +2450,7 @@ TEST_F(WebContentsImplTest, NewInterstitialDoesNotCancelPendingEntry) {
TestInterstitialPageStateGuard state_guard2(interstitial2);
interstitial2->Show();
interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial2->TestDidNavigate(1, interstitial_entry_id, true, kGURL);
+ interstitial2->TestDidNavigate(interstitial_entry_id, true, kGURL);
// Make sure we still have an entry.
NavigationEntry* entry = contents()->GetController().GetPendingEntry();
@@ -2507,7 +2477,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
// DidNavigate from the page
- contents()->TestDidNavigate(main_test_rfh(), 1, entry_id, true,
+ contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
kGURL, ui::PAGE_TRANSITION_TYPED);
// Simulate showing an interstitial while the page is showing.
@@ -2519,7 +2489,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, kGURL);
// While the interstitial is showing, let's simulate the hidden page
// attempting to show a JS message.
@@ -2536,7 +2506,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1);
+ main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -2553,7 +2523,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url2);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_EQ(2, controller().GetEntryCount());
@@ -2604,7 +2574,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneTargetInterstitial) {
interstitial->Show();
int interstitial_entry_id =
other_controller.GetTransientEntry()->GetUniqueID();
- interstitial->TestDidNavigate(1, interstitial_entry_id, true, url3);
+ interstitial->TestDidNavigate(interstitial_entry_id, true, url3);
EXPECT_TRUE(interstitial->is_showing());
EXPECT_EQ(2, other_controller.GetEntryCount());
@@ -2940,7 +2910,7 @@ TEST_F(WebContentsImplTest, ActiveContentsCountNavigate) {
contents->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents->CrossProcessNavigationPending());
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
- contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kUrl);
+ contents->GetPendingMainFrame()->SendNavigate(entry_id, true, kUrl);
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
contents.reset();
@@ -2985,7 +2955,7 @@ TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
EXPECT_EQ(0u, instance_webui->GetRelatedActiveContentsCount());
// Commit and contents counts for the new one.
- contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kWebUIUrl);
+ contents->GetPendingMainFrame()->SendNavigate(entry_id, true, kWebUIUrl);
EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
EXPECT_EQ(1u, instance_webui->GetRelatedActiveContentsCount());
@@ -3056,7 +3026,7 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
FrameHostMsg_DidStartLoading(orig_rfh->GetRoutingID(), false));
}
main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, main_url,
+ contents()->TestDidNavigate(orig_rfh, entry_id, true, main_url,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -3073,7 +3043,7 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
subframe->OnMessageReceived(
FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
}
- subframe->SendNavigateWithTransition(1, 0, false, initial_url,
+ subframe->SendNavigateWithTransition(0, false, initial_url,
ui::PAGE_TRANSITION_AUTO_SUBFRAME);
subframe->OnMessageReceived(
FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
@@ -3088,7 +3058,7 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
subframe->OnMessageReceived(
FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
}
- subframe->SendNavigateWithTransition(1, 0, false, foo_url,
+ subframe->SendNavigateWithTransition(10, false, foo_url,
ui::PAGE_TRANSITION_AUTO_SUBFRAME);
subframe->OnMessageReceived(
FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
@@ -3124,7 +3094,7 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
// Commit the navigation in the child frame and send the DidStopLoading
// message.
subframe->PrepareForCommit();
- contents()->TestDidNavigate(subframe, 3, entry_id, true, bar_url,
+ contents()->TestDidNavigate(subframe, entry_id, true, bar_url,
ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
subframe->OnMessageReceived(
FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
@@ -3186,7 +3156,7 @@ TEST_F(WebContentsImplTest, NoEarlyStop) {
// navigation in the current RenderFrameHost. There should still be a pending
// RenderFrameHost and the WebContents should still be loading.
current_rfh->SendNavigateWithModificationCallback(
- 1, 0, true, kUrl3, base::Bind(SetAsNonUserGesture));
+ 0, true, kUrl3, base::Bind(SetAsNonUserGesture));
current_rfh->OnMessageReceived(
FrameHostMsg_DidStopLoading(current_rfh->GetRoutingID()));
EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh);
@@ -3197,7 +3167,7 @@ TEST_F(WebContentsImplTest, NoEarlyStop) {
// Commit the navigation. The formerly pending RenderFrameHost should now be
// the current RenderFrameHost and the WebContents should still be loading.
- contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, kUrl2,
+ contents()->TestDidNavigate(pending_rfh, entry_id, true, kUrl2,
ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->GetPendingMainFrame());
TestRenderFrameHost* new_current_rfh = main_test_rfh();
@@ -3229,21 +3199,17 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
// Ensure RenderFrame is initialized before simulating events coming from it.
main_test_rfh()->InitializeRenderFrameIfNeeded();
- // The audio power save blocker should not be based on having a media player
- // when audio stream monitoring is available.
- if (AudioStreamMonitor::monitoring_available()) {
- // Send a fake audio stream monitor notification. The audio power save
- // blocker should be created.
- monitor->set_was_recently_audible_for_testing(true);
- contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- EXPECT_TRUE(has_audio_power_save_blocker());
-
- // Send another fake notification, this time when WasRecentlyAudible() will
- // be false. The power save blocker should be released.
- monitor->set_was_recently_audible_for_testing(false);
- contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- EXPECT_FALSE(has_audio_power_save_blocker());
- }
+ // Send a fake audio stream monitor notification. The audio power save
+ // blocker should be created.
+ monitor->set_was_recently_audible_for_testing(true);
+ contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ EXPECT_TRUE(has_audio_power_save_blocker());
+
+ // Send another fake notification, this time when WasRecentlyAudible() will
+ // be false. The power save blocker should be released.
+ monitor->set_was_recently_audible_for_testing(false);
+ contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Start a player with both audio and video. A video power save blocker
// should be created. If audio stream monitoring is available, an audio power
@@ -3252,8 +3218,7 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
0, kPlayerAudioVideoId, true, true, false,
media::MediaContentType::Persistent));
EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Upon hiding the video power save blocker should be released.
contents()->WasHidden();
@@ -3266,8 +3231,7 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
0, kPlayerVideoOnlyId, true, false, false,
media::MediaContentType::Persistent));
EXPECT_FALSE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Showing the WebContents should result in the creation of the blocker.
contents()->WasShown();
@@ -3279,8 +3243,7 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
0, kPlayerAudioOnlyId, false, true, false,
media::MediaContentType::Persistent));
EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Start a remote player. There should be no change in the power save
// blockers.
@@ -3288,16 +3251,14 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
0, kPlayerRemoteId, true, true, true,
media::MediaContentType::Persistent));
EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Destroy the original audio video player. Both power save blockers should
// remain.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerAudioVideoId, false));
EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Destroy the audio only player. The video power save blocker should remain.
rfh->OnMessageReceived(
@@ -3324,8 +3285,7 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
0, kPlayerAudioVideoId, true, true, false,
media::MediaContentType::Persistent));
EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_EQ(has_audio_power_save_blocker(),
- !AudioStreamMonitor::monitoring_available());
+ EXPECT_FALSE(has_audio_power_save_blocker());
// Crash the renderer.
main_test_rfh()->GetProcess()->SimulateCrash();
@@ -3427,9 +3387,12 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
return true;
}
- void CancelActiveAndPendingDialogs(WebContents* web_contents) override {}
-
- void ResetDialogState(WebContents* web_contents) override { ++reset_count_; }
+ void CancelDialogs(WebContents* web_contents,
+ bool suppress_callbacks,
+ bool reset_state) override {
+ if (reset_state)
+ ++reset_count_;
+ }
private:
size_t reset_count_ = 0;
@@ -3444,14 +3407,14 @@ TEST_F(WebContentsImplTest, ResetJavaScriptDialogOnUserNavigate) {
contents()->SetJavaScriptDialogManagerForTesting(&dialog_manager);
// A user-initiated navigation.
- contents()->TestDidNavigate(main_test_rfh(), 1, 0, true,
+ contents()->TestDidNavigate(main_test_rfh(), 0, true,
GURL("about:whatever"),
ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(1u, dialog_manager.reset_count());
// An automatic navigation.
main_test_rfh()->SendNavigateWithModificationCallback(
- 2, 0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
+ 0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
EXPECT_EQ(1u, dialog_manager.reset_count());
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 0222bc629b4..37db35ebb15 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -7,6 +7,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
+#include "cc/layers/layer.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
@@ -28,10 +29,8 @@ using base::android::ScopedJavaLocalRef;
namespace content {
-// static
-void WebContentsView::GetDefaultScreenInfo(ScreenInfo* results) {
- const display::Display& display =
- display::Screen::GetScreen()->GetPrimaryDisplay();
+namespace {
+void DisplayToScreenInfo(const display::Display& display, ScreenInfo* results) {
results->rect = display.bounds();
// TODO(husky): Remove any system controls from availableRect.
results->available_rect = display.work_area();
@@ -44,6 +43,29 @@ void WebContentsView::GetDefaultScreenInfo(ScreenInfo* results) {
results->depth_per_component = display.depth_per_component();
results->is_monochrome = display.is_monochrome();
}
+}
+
+// static
+void WebContentsView::GetDefaultScreenInfo(ScreenInfo* results) {
+ DisplayToScreenInfo(display::Screen::GetScreen()->GetPrimaryDisplay(),
+ results);
+}
+
+// static
+void SynchronousCompositor::SetClientForWebContents(
+ WebContents* contents,
+ SynchronousCompositorClient* client) {
+ DCHECK(contents);
+ DCHECK(client);
+ WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
+ static_cast<WebContentsImpl*>(contents)->GetView());
+ DCHECK(!wcva->synchronous_compositor_client());
+ wcva->set_synchronous_compositor_client(client);
+ RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
+ contents->GetRenderWidgetHostView());
+ if (rwhv)
+ rwhv->SetSynchronousCompositorClient(client);
+}
WebContentsView* CreateWebContentsView(
WebContentsImpl* web_contents,
@@ -60,10 +82,13 @@ WebContentsViewAndroid::WebContentsViewAndroid(
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
content_view_core_(NULL),
- delegate_(delegate) {
+ delegate_(delegate),
+ synchronous_compositor_client_(nullptr) {
}
WebContentsViewAndroid::~WebContentsViewAndroid() {
+ if (view_.GetLayer())
+ view_.GetLayer()->RemoveFromParent();
}
void WebContentsViewAndroid::SetContentViewCore(
@@ -87,7 +112,7 @@ void WebContentsViewAndroid::SetContentViewCore(
}
gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
- return content_view_core_ ? content_view_core_->GetViewAndroid() : nullptr;
+ return const_cast<gfx::NativeView>(&view_);
}
gfx::NativeView WebContentsViewAndroid::GetContentNativeView() const {
@@ -104,8 +129,14 @@ gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const {
}
void WebContentsViewAndroid::GetScreenInfo(ScreenInfo* result) const {
- // ScreenInfo isn't tied to the widget on Android. Always return the default.
- WebContentsView::GetDefaultScreenInfo(result);
+ // Since API 17 Android supports multiple displays with different properties.
+
+ gfx::NativeView native_view = GetNativeView();
+ display::Display display =
+ native_view
+ ? display::Screen::GetScreen()->GetDisplayNearestWindow(native_view)
+ : display::Screen::GetScreen()->GetPrimaryDisplay();
+ DisplayToScreenInfo(display, result);
}
void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const {
@@ -126,10 +157,15 @@ void WebContentsViewAndroid::SizeContents(const gfx::Size& size) {
}
void WebContentsViewAndroid::Focus() {
- if (web_contents_->ShowingInterstitialPage())
+ RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
+ web_contents_->GetRenderWidgetHostView());
+ if (web_contents_->ShowingInterstitialPage()) {
web_contents_->GetInterstitialPage()->Focus();
- else
- web_contents_->GetRenderWidgetHostView()->Focus();
+ if (content_view_core_)
+ content_view_core_->ForceUpdateImeAdapter(rwhv->GetNativeImeAdapter());
+ } else {
+ rwhv->Focus();
+ }
}
void WebContentsViewAndroid::SetInitialFocus() {
@@ -181,7 +217,10 @@ RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForWidget(
// order to paint it. See ContentView::GetRenderWidgetHostViewAndroid for an
// example of how this is achieved for InterstitialPages.
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(render_widget_host);
- return new RenderWidgetHostViewAndroid(rwhi, content_view_core_);
+ RenderWidgetHostViewAndroid* rwhv =
+ new RenderWidgetHostViewAndroid(rwhi, content_view_core_);
+ rwhv->SetSynchronousCompositorClient(synchronous_compositor_client_);
+ return rwhv;
}
RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForPopupWidget(
@@ -231,7 +270,8 @@ void WebContentsViewAndroid::StartDragging(
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
if (drop_data.text.is_null()) {
// Need to clear drag and drop state in blink.
OnDragEnded();
@@ -276,6 +316,10 @@ void WebContentsViewAndroid::UpdateDragCursor(blink::WebDragOperation op) {
// Intentional no-op because Android does not have cursor.
}
+// TODO(paulmeyer): The drag-and-drop calls on GetRenderViewHost()->GetWidget()
+// in the following functions will need to be targeted to specific
+// RenderWidgetHosts in order to work with OOPIFs. See crbug.com/647249.
+
void WebContentsViewAndroid::OnDragEntered(
const std::vector<DropData::Metadata>& metadata,
const gfx::Point& location,
@@ -283,8 +327,9 @@ void WebContentsViewAndroid::OnDragEntered(
blink::WebDragOperationsMask allowed_ops =
static_cast<blink::WebDragOperationsMask>(blink::WebDragOperationCopy |
blink::WebDragOperationMove);
- web_contents_->GetRenderViewHost()->DragTargetDragEnterWithMetaData(
- metadata, location, screen_location, allowed_ops, 0);
+ web_contents_->GetRenderViewHost()->GetWidget()->
+ DragTargetDragEnterWithMetaData(metadata, location, screen_location,
+ allowed_ops, 0);
}
void WebContentsViewAndroid::OnDragUpdated(const gfx::Point& location,
@@ -292,24 +337,24 @@ void WebContentsViewAndroid::OnDragUpdated(const gfx::Point& location,
blink::WebDragOperationsMask allowed_ops =
static_cast<blink::WebDragOperationsMask>(blink::WebDragOperationCopy |
blink::WebDragOperationMove);
- web_contents_->GetRenderViewHost()->DragTargetDragOver(
+ web_contents_->GetRenderViewHost()->GetWidget()->DragTargetDragOver(
location, screen_location, allowed_ops, 0);
}
void WebContentsViewAndroid::OnDragExited() {
- web_contents_->GetRenderViewHost()->DragTargetDragLeave();
+ web_contents_->GetRenderViewHost()->GetWidget()->DragTargetDragLeave();
}
void WebContentsViewAndroid::OnPerformDrop(DropData* drop_data,
const gfx::Point& location,
const gfx::Point& screen_location) {
- web_contents_->GetRenderViewHost()->FilterDropData(drop_data);
- web_contents_->GetRenderViewHost()->DragTargetDrop(*drop_data, location,
- screen_location, 0);
+ web_contents_->GetRenderViewHost()->GetWidget()->FilterDropData(drop_data);
+ web_contents_->GetRenderViewHost()->GetWidget()->DragTargetDrop(
+ *drop_data, location, screen_location, 0);
}
void WebContentsViewAndroid::OnDragEnded() {
- web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();
+ web_contents_->GetRenderViewHost()->GetWidget()->DragSourceSystemDragEnded();
}
void WebContentsViewAndroid::GotFocus() {
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 771047b97ee..1a5ec57e6e4 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -13,10 +13,13 @@
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/drop_data.h"
+#include "ui/android/view_android.h"
#include "ui/gfx/geometry/rect_f.h"
namespace content {
class ContentViewCoreImpl;
+class RenderWidgetHostViewAndroid;
+class SynchronousCompositorClient;
class WebContentsImpl;
// Android-specific implementation of the WebContentsView.
@@ -32,6 +35,14 @@ class WebContentsViewAndroid : public WebContentsView,
// by the UI frontend.
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
+ void set_synchronous_compositor_client(SynchronousCompositorClient* client) {
+ synchronous_compositor_client_ = client;
+ }
+
+ SynchronousCompositorClient* synchronous_compositor_client() const {
+ return synchronous_compositor_client_;
+ }
+
// WebContentsView implementation --------------------------------------------
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
@@ -73,7 +84,8 @@ class WebContentsViewAndroid : public WebContentsView,
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
@@ -99,6 +111,12 @@ class WebContentsViewAndroid : public WebContentsView,
// Interface for extensions to WebContentsView. Used to show the context menu.
std::unique_ptr<WebContentsViewDelegate> delegate_;
+ // The native view associated with the contents of the web.
+ ui::ViewAndroid view_;
+
+ // Interface used to get notified of events from the synchronous compositor.
+ SynchronousCompositorClient* synchronous_compositor_client_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAndroid);
};
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 151855085a3..7ac49469fe4 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -23,6 +23,7 @@
#include "content/browser/renderer_host/render_view_host_factory.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_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
@@ -40,14 +41,17 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
+#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "net/base/filename_util.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
@@ -71,10 +75,9 @@
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/touch_selection/touch_selection_controller.h"
-#include "ui/wm/public/drag_drop_client.h"
-#include "ui/wm/public/drag_drop_delegate.h"
namespace content {
+
WebContentsView* CreateWebContentsView(
WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate,
@@ -244,6 +247,7 @@ void WriteFileSystemFilesToPickle(
for (size_t i = 0; i < file_system_files.size(); ++i) {
pickle->WriteString(file_system_files[i].url.spec());
pickle->WriteInt64(file_system_files[i].size);
+ pickle->WriteString(file_system_files[i].filesystem_id);
}
}
@@ -261,8 +265,11 @@ bool ReadFileSystemFilesFromPickle(
for (uint32_t i = 0; i < num_files; ++i) {
std::string url_string;
int64_t size = 0;
- if (!iter.ReadString(&url_string) || !iter.ReadInt64(&size))
+ std::string filesystem_id;
+ if (!iter.ReadString(&url_string) || !iter.ReadInt64(&size) ||
+ !iter.ReadString(&filesystem_id)) {
return false;
+ }
GURL url(url_string);
if (!url.is_valid())
@@ -270,6 +277,7 @@ bool ReadFileSystemFilesFromPickle(
(*file_system_files)[i].url = url;
(*file_system_files)[i].size = size;
+ (*file_system_files)[i].filesystem_id = filesystem_id;
}
return true;
}
@@ -399,6 +407,10 @@ int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
return web_input_event_modifiers;
}
+GlobalRoutingID GetRenderViewHostID(RenderViewHost* rvh) {
+ return GlobalRoutingID(rvh->GetProcess()->GetID(), rvh->GetRoutingID());
+}
+
} // namespace
class WebContentsViewAura::WindowObserver
@@ -513,8 +525,11 @@ WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
: web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::WebDragOperationNone),
- drag_dest_delegate_(NULL),
- current_rvh_for_drag_(NULL),
+ drag_dest_delegate_(nullptr),
+ current_rvh_for_drag_(ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE),
+ drag_start_process_id_(ChildProcessHost::kInvalidUniqueID),
+ drag_start_view_id_(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE),
current_overscroll_gesture_(OVERSCROLL_NONE),
completed_overscroll_gesture_(OVERSCROLL_NONE),
navigation_overlay_(nullptr),
@@ -549,7 +564,12 @@ void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
rwhv->SetSize(size);
}
-void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
+void WebContentsViewAura::EndDrag(RenderWidgetHost* source_rwh,
+ blink::WebDragOperationsMask ops) {
+ drag_start_process_id_ = ChildProcessHost::kInvalidUniqueID;
+ drag_start_view_id_ = GlobalRoutingID(ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE);
+
if (!web_contents_)
return;
@@ -559,10 +579,15 @@ void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(window->GetRootWindow());
if (screen_position_client)
- screen_position_client->ConvertPointFromScreen(window, &client_loc);
+ screen_position_client->ConvertPointFromScreen(window, &client_loc);
+ // TODO(paulmeyer): In the OOPIF case, should |client_loc| be converted to the
+ // coordinates local to |source_rwh|? See crbug.com/647249.
web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
- screen_loc.x(), screen_loc.y(), ops);
+ screen_loc.x(), screen_loc.y(), ops,
+ source_rwh);
+
+ web_contents_->SystemDragEnded(source_rwh);
}
void WebContentsViewAura::InstallOverscrollControllerDelegate(
@@ -622,6 +647,13 @@ gfx::NativeView WebContentsViewAura::GetRenderWidgetHostViewParent() const {
return window_.get();
}
+bool WebContentsViewAura::IsValidDragTarget(
+ RenderWidgetHostImpl* target_rwh) const {
+ return target_rwh->GetProcess()->GetID() == drag_start_process_id_ ||
+ GetRenderViewHostID(web_contents_->GetRenderViewHost()) !=
+ drag_start_view_id_;
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, WebContentsView implementation:
@@ -879,13 +911,25 @@ void WebContentsViewAura::StartDragging(
blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
aura::Window* root_window = GetNativeView()->GetRootWindow();
if (!aura::client::GetDragDropClient(root_window)) {
- web_contents_->SystemDragEnded();
+ web_contents_->SystemDragEnded(source_rwh);
return;
}
+ // Grab a weak pointer to the RenderWidgetHost, since it can be destroyed
+ // during the drag and drop nested message loop in StartDragAndDrop.
+ // For example, the RenderWidgetHost can be deleted if a cross-process
+ // transfer happens while dragging, since the RenderWidgetHost is deleted in
+ // that case.
+ base::WeakPtr<RenderWidgetHostImpl> source_rwh_weak_ptr =
+ source_rwh->GetWeakPtr();
+
+ drag_start_process_id_ = source_rwh->GetProcess()->GetID();
+ drag_start_view_id_ = GetRenderViewHostID(web_contents_->GetRenderViewHost());
+
ui::TouchSelectionController* selection_controller = GetSelectionController();
if (selection_controller)
selection_controller->HideAndDisallowShowingAutomatically();
@@ -928,8 +972,7 @@ void WebContentsViewAura::StartDragging(
return;
}
- EndDrag(ConvertToWeb(result_op));
- web_contents_->SystemDragEnded();
+ EndDrag(source_rwh_weak_ptr.get(), ConvertToWeb(result_op));
}
void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
@@ -1109,12 +1152,21 @@ void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
// WebContentsViewAura, aura::client::DragDropDelegate implementation:
void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
- current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
- current_drop_data_.reset(new DropData());
+ gfx::Point transformed_pt;
+ RenderWidgetHostImpl* target_rwh =
+ web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+ web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+ event.location(), &transformed_pt);
- PrepareDropData(current_drop_data_.get(), event.data());
+ if (!IsValidDragTarget(target_rwh))
+ return;
- web_contents_->GetRenderViewHost()->FilterDropData(current_drop_data_.get());
+ current_rwh_for_drag_ = target_rwh->GetWeakPtr();
+ current_rvh_for_drag_ =
+ GetRenderViewHostID(web_contents_->GetRenderViewHost());
+ current_drop_data_.reset(new DropData());
+ PrepareDropData(current_drop_data_.get(), event.data());
+ current_rwh_for_drag_->FilterDropData(current_drop_data_.get());
blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
@@ -1130,8 +1182,8 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
drag_dest_delegate_->DragInitialize(web_contents_);
gfx::Point screen_pt = display::Screen::GetScreen()->GetCursorScreenPoint();
- web_contents_->GetRenderViewHost()->DragTargetDragEnter(
- *current_drop_data_, event.location(), screen_pt, op,
+ current_rwh_for_drag_->DragTargetDragEnter(
+ *current_drop_data_, transformed_pt, screen_pt, op,
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_) {
@@ -1141,17 +1193,28 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
}
int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
- DCHECK(current_rvh_for_drag_);
- if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
+ gfx::Point transformed_pt;
+ RenderWidgetHostImpl* target_rwh =
+ web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+ web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+ event.location(), &transformed_pt);
+
+ if (!IsValidDragTarget(target_rwh))
+ return ui::DragDropTypes::DRAG_NONE;
+
+ if (target_rwh != current_rwh_for_drag_.get()) {
+ if (current_rwh_for_drag_)
+ current_rwh_for_drag_->DragTargetDragLeave();
OnDragEntered(event);
+ }
if (!current_drop_data_)
return ui::DragDropTypes::DRAG_NONE;
blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
- gfx::Point screen_pt = display::Screen::GetScreen()->GetCursorScreenPoint();
- web_contents_->GetRenderViewHost()->DragTargetDragOver(
- event.location(), screen_pt, op,
+ gfx::Point screen_pt = event.root_location();
+ target_rwh->DragTargetDragOver(
+ transformed_pt, screen_pt, op,
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_)
@@ -1161,14 +1224,17 @@ int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
}
void WebContentsViewAura::OnDragExited() {
- DCHECK(current_rvh_for_drag_);
- if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
+ if (current_rvh_for_drag_ !=
+ GetRenderViewHostID(web_contents_->GetRenderViewHost()) ||
+ !current_drop_data_) {
return;
+ }
- if (!current_drop_data_)
- return;
+ if (current_rwh_for_drag_) {
+ current_rwh_for_drag_->DragTargetDragLeave();
+ current_rwh_for_drag_.reset();
+ }
- web_contents_->GetRenderViewHost()->DragTargetDragLeave();
if (drag_dest_delegate_)
drag_dest_delegate_->OnDragLeave();
@@ -1176,15 +1242,26 @@ void WebContentsViewAura::OnDragExited() {
}
int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
- DCHECK(current_rvh_for_drag_);
- if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
+ gfx::Point transformed_pt;
+ RenderWidgetHostImpl* target_rwh =
+ web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+ web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+ event.location(), &transformed_pt);
+
+ if (!IsValidDragTarget(target_rwh))
+ return ui::DragDropTypes::DRAG_NONE;
+
+ if (target_rwh != current_rwh_for_drag_.get()) {
+ if (current_rwh_for_drag_)
+ current_rwh_for_drag_->DragTargetDragLeave();
OnDragEntered(event);
+ }
if (!current_drop_data_)
return ui::DragDropTypes::DRAG_NONE;
- web_contents_->GetRenderViewHost()->DragTargetDrop(
- *current_drop_data_, event.location(),
+ target_rwh->DragTargetDrop(
+ *current_drop_data_, transformed_pt,
display::Screen::GetScreen()->GetCursorScreenPoint(),
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_)
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 673045ad475..2e7beabcc43 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -11,13 +11,15 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/loader/global_routing_id.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/content_export.h"
+#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_observer.h"
-#include "ui/wm/public/drag_drop_delegate.h"
namespace aura {
class Window;
@@ -33,7 +35,6 @@ class GestureNavSimple;
class OverscrollNavigationOverlay;
class RenderWidgetHostImpl;
class RenderWidgetHostViewAura;
-class ShadowLayerDelegate;
class TouchSelectionControllerClientAura;
class WebContentsViewDelegate;
class WebContentsImpl;
@@ -66,7 +67,7 @@ class CONTENT_EXPORT WebContentsViewAura
void SizeChangedCommon(const gfx::Size& size);
- void EndDrag(blink::WebDragOperationsMask ops);
+ void EndDrag(RenderWidgetHost* source_rwh, blink::WebDragOperationsMask ops);
void InstallOverscrollControllerDelegate(RenderWidgetHostViewAura* view);
@@ -87,6 +88,11 @@ class CONTENT_EXPORT WebContentsViewAura
// Returns GetNativeView unless overridden for testing.
gfx::NativeView GetRenderWidgetHostViewParent() const;
+ // Returns whether |target_rwh| is a valid RenderWidgetHost to be dragging
+ // over. This enforces that same-page, cross-site drags are not allowed. See
+ // crbug.com/666858.
+ bool IsValidDragTarget(RenderWidgetHostImpl* target_rwh) const;
+
// Overridden from WebContentsView:
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
@@ -119,7 +125,8 @@ class CONTENT_EXPORT WebContentsViewAura
blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
@@ -193,11 +200,28 @@ class CONTENT_EXPORT WebContentsViewAura
WebDragDestDelegate* drag_dest_delegate_;
- // We keep track of the render view host we're dragging over. If it changes
- // during a drag, we need to re-send the DragEnter message. WARNING:
- // this pointer should never be dereferenced. We only use it for comparing
- // pointers.
- void* current_rvh_for_drag_;
+ // We keep track of the RenderWidgetHost we're dragging over. If it changes
+ // during a drag, we need to re-send the DragEnter message.
+ base::WeakPtr<RenderWidgetHostImpl> current_rwh_for_drag_;
+
+ // We also keep track of the ID of the RenderViewHost we're dragging over to
+ // avoid sending the drag exited message after leaving the current view.
+ GlobalRoutingID current_rvh_for_drag_;
+
+ // We track the IDs of the source RenderProcessHost and RenderViewHost from
+ // which the current drag originated. These are used to ensure that drag
+ // events do not fire over a cross-site frame (with respect to the source
+ // frame) in the same page (see crbug.com/666858). Specifically, the
+ // RenderViewHost is used to check the "same page" property, while the
+ // RenderProcessHost is used to check the "cross-site" property. Note that the
+ // reason the RenderProcessHost is tracked instead of the RenderWidgetHost is
+ // so that we still allow drags between non-contiguous same-site frames (such
+ // frames will have the same process, but different widgets). Note also that
+ // the RenderViewHost may not be in the same process as the RenderProcessHost,
+ // since the view corresponds to the page, while the process is specific to
+ // the frame from which the drag started.
+ int drag_start_process_id_;
+ GlobalRoutingID drag_start_view_id_;
// The overscroll gesture currently in progress.
OverscrollMode current_overscroll_gesture_;
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 b296438b5c1..9b17012781b 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
@@ -167,7 +167,8 @@ void WebContentsViewChildFrame::StartDragging(
WebDragOperationsMask ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
NOTREACHED();
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.h b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
index 4158bf10be7..c83f2f014c2 100644
--- a/chromium/content/browser/web_contents/web_contents_view_child_frame.h
+++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
@@ -14,7 +14,6 @@ namespace content {
class WebContents;
class WebContentsImpl;
class WebContentsViewDelegate;
-class BrowserPluginGuest;
class WebContentsViewChildFrame : public WebContentsView,
public RenderViewHostDelegateView {
@@ -62,7 +61,8 @@ class WebContentsViewChildFrame : public WebContentsView,
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.cc b/chromium/content/browser/web_contents/web_contents_view_guest.cc
index f7e452de43e..b2b86fa755e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -229,7 +229,8 @@ void WebContentsViewGuest::StartDragging(
WebDragOperationsMask ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
WebContentsImpl* embedder_web_contents = guest_->embedder_web_contents();
embedder_web_contents->GetBrowserPluginEmbedder()->StartDrag(guest_);
RenderViewHostImpl* embedder_render_view_host =
@@ -240,9 +241,10 @@ void WebContentsViewGuest::StartDragging(
embedder_render_view_host->GetDelegate()->GetDelegateView();
if (view) {
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.StartDrag"));
- view->StartDragging(drop_data, ops, image, image_offset, event_info);
+ view->StartDragging(
+ drop_data, ops, image, image_offset, event_info, source_rwh);
} else {
- embedder_web_contents->SystemDragEnded();
+ embedder_web_contents->SystemDragEnded(source_rwh);
}
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.h b/chromium/content/browser/web_contents/web_contents_view_guest.h
index 8c8a4a13c8a..0102d7ee960 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.h
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.h
@@ -79,7 +79,8 @@ class WebContentsViewGuest : public WebContentsView,
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
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 4dc067f142f..3b34cbd7717 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -21,7 +21,6 @@
#include "ui/gfx/geometry/size.h"
@class FocusTracker;
-class SkBitmap;
@class WebDragDest;
@class WebDragSource;
@@ -116,7 +115,8 @@ class WebContentsViewMac : public WebContentsView,
blink::WebDragOperationsMask allowed_operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
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 5a1368d92f5..ea529e53428 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -65,6 +65,7 @@ STATIC_ASSERT_ENUM(NSDragOperationEvery, blink::WebDragOperationEvery);
- (void)setCurrentDragOperation:(NSDragOperation)operation;
- (DropData*)dropData;
- (void)startDragWithDropData:(const DropData&)dropData
+ sourceRWH:(content::RenderWidgetHostImpl*)sourceRWH
dragOperationMask:(NSDragOperation)operationMask
image:(NSImage*)image
offset:(NSPoint)offset;
@@ -174,7 +175,8 @@ void WebContentsViewMac::StartDragging(
WebDragOperationsMask allowed_operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
// By allowing nested tasks, the code below also allows Close(),
// which would deallocate |this|. The same problem can occur while
// processing -sendEvent:, so Close() is deferred in that case.
@@ -190,6 +192,7 @@ void WebContentsViewMac::StartDragging(
NSPoint offset = NSPointFromCGPoint(
gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint());
[cocoa_view_ startDragWithDropData:drop_data
+ sourceRWH:source_rwh
dragOperationMask:mask
image:gfx::NSImageFromImageSkia(image)
offset:offset];
@@ -540,19 +543,22 @@ void WebContentsViewMac::CloseTab() {
}
- (void)startDragWithDropData:(const DropData&)dropData
+ sourceRWH:(content::RenderWidgetHostImpl*)sourceRWH
dragOperationMask:(NSDragOperation)operationMask
image:(NSImage*)image
offset:(NSPoint)offset {
if (![self webContents])
return;
+ [dragDest_ setDragStartTrackersForProcess:sourceRWH->GetProcess()->GetID()];
dragSource_.reset([[WebDragSource alloc]
- initWithContents:[self webContents]
- view:self
- dropData:&dropData
- image:image
- offset:offset
- pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
- dragOperationMask:operationMask]);
+ initWithContents:[self webContents]
+ view:self
+ dropData:&dropData
+ sourceRWH:sourceRWH
+ image:image
+ offset:offset
+ pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
+ dragOperationMask:operationMask]);
[dragSource_ startDrag];
}
@@ -656,13 +662,20 @@ void WebContentsViewMac::CloseTab() {
webContents->UpdateWebContentsVisibility(viewVisible);
}
-// When the subviews require a layout, their size should be reset to the size
-// of this view. (It is possible for the size to get out of sync as an
-// optimization in preparation for an upcoming WebContentsView resize.
-// http://crbug.com/264207)
- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
- for (NSView* subview in self.subviews)
- [subview setFrame:self.bounds];
+ // Subviews do not participate in auto layout unless the the size this view
+ // changes. This allows RenderWidgetHostViewMac::SetBounds(..) to select a
+ // size of the subview that differs from its superview in preparation for an
+ // upcoming WebContentsView resize.
+ // See http://crbug.com/264207 and http://crbug.com/655112.
+}
+
+- (void)setFrameSize:(NSSize)newSize {
+ [super setFrameSize:newSize];
+
+ // Perform manual layout of subviews, e.g., when the window size changes.
+ for (NSView* subview in [self subviews])
+ [subview setFrame:[self bounds]];
}
- (void)viewWillMoveToWindow:(NSWindow*)newWindow {
diff --git a/chromium/content/browser/web_contents/web_contents_view_mus.cc b/chromium/content/browser/web_contents/web_contents_view_mus.cc
index cfdc9b1dbca..959a27f9c7e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mus.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_mus.cc
@@ -13,7 +13,7 @@
#include "services/ui/public/cpp/window.h"
#include "services/ui/public/cpp/window_tree_client.h"
#include "third_party/WebKit/public/platform/WebDragOperation.h"
-#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
@@ -207,7 +207,8 @@ void WebContentsViewMus::StartDragging(const DropData& drop_data,
WebDragOperationsMask ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) {
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) {
// TODO(fsamuel): Implement drag and drop.
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_mus.h b/chromium/content/browser/web_contents/web_contents_view_mus.h
index 99cc7469854..f47f8e3bf3c 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mus.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mus.h
@@ -20,6 +20,7 @@
namespace content {
+class RenderWidgetHostImpl;
class WebContents;
class WebContentsImpl;
class WebContentsViewDelegate;
@@ -80,7 +81,8 @@ class WebContentsViewMus : public WebContentsView,
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) override;
+ const DragEventSourceInfo& event_info,
+ RenderWidgetHostImpl* source_rwh) override;
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.h b/chromium/content/browser/web_contents/web_drag_dest_mac.h
index 2598ee0e886..da4427bca57 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.h
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.h
@@ -7,11 +7,14 @@
#include <memory>
#include "base/strings/string16.h"
+#include "content/browser/loader/global_routing_id.h"
#include "content/common/content_export.h"
#include "content/public/common/drop_data.h"
+#include "ui/gfx/geometry/point.h"
namespace content {
class RenderViewHost;
+class RenderWidgetHostImpl;
class WebContentsImpl;
class WebDragDestDelegate;
}
@@ -35,10 +38,22 @@ CONTENT_EXPORT
// allow the drop.
NSDragOperation currentOperation_;
+ // Tracks the current RenderWidgetHost we're dragging over.
+ base::WeakPtr<content::RenderWidgetHostImpl> currentRWHForDrag_;
+
// Keep track of the render view host we're dragging over. If it changes
// during a drag, we need to re-send the DragEnter message.
RenderViewHostIdentifier currentRVH_;
+ // Tracks the IDs of the source RenderProcessHost and RenderViewHost from
+ // which the current drag originated. These are set in
+ // -setDragStartTrackersForProcess:, and are used to ensure that drag events
+ // do not fire over a cross-site frame (with respect to the source frame) in
+ // the same page (see crbug.com/666858). See
+ // WebContentsViewAura::drag_start_process_id_ for additional information.
+ int dragStartProcessID_;
+ content::GlobalRoutingID dragStartViewID_;
+
// The data for the current drag, or NULL if none is in progress.
std::unique_ptr<content::DropData> dropData_;
@@ -67,8 +82,20 @@ CONTENT_EXPORT
- (void)draggingExited:(id<NSDraggingInfo>)info;
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
view:(NSView*)view;
-- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
- view:(NSView*)view;
+- (BOOL)performDragOperation:(id<NSDraggingInfo>)info view:(NSView*)view;
+
+// Helper to call WebWidgetHostInputEventRouter::GetRenderWidgetHostAtPoint().
+- (content::RenderWidgetHostImpl*)
+GetRenderWidgetHostAtPoint:(const NSPoint&)viewPoint
+ transformedPt:(gfx::Point*)transformedPt;
+
+// Sets |dragStartProcessID_| and |dragStartViewID_|.
+- (void)setDragStartTrackersForProcess:(int)processID;
+
+// Returns whether |targetRWH| is a valid RenderWidgetHost to be dragging
+// over. This enforces that same-page, cross-site drags are not allowed. See
+// crbug.com/666858.
+- (bool)isValidDragTarget:(content::RenderWidgetHostImpl*)targetRWH;
@end
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.mm b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
index 9e595764594..458b01aaeed 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -8,16 +8,20 @@
#include "base/strings/sys_string_conversions.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_input_event_router.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
+#include "content/public/common/child_process_host.h"
#include "content/public/common/drop_data.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/base/window_open_disposition.h"
+#include "ui/gfx/geometry/point.h"
using blink::WebDragOperationsMask;
using content::DropData;
@@ -54,6 +58,11 @@ int GetModifierFlags() {
return modifier_state;
}
+content::GlobalRoutingID GetRenderViewHostID(content::RenderViewHost* rvh) {
+ return content::GlobalRoutingID(rvh->GetProcess()->GetID(),
+ rvh->GetRoutingID());
+}
+
} // namespace
@implementation WebDragDest
@@ -65,6 +74,9 @@ int GetModifierFlags() {
if ((self = [super init])) {
webContents_ = contents;
canceled_ = false;
+ dragStartProcessID_ = content::ChildProcessHost::kInvalidUniqueID;
+ dragStartViewID_ = content::GlobalRoutingID(
+ content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
}
return self;
}
@@ -125,12 +137,35 @@ int GetModifierFlags() {
// we need to send a new enter message in draggingUpdated:.
currentRVH_ = webContents_->GetRenderViewHost();
+ // Create the appropriate mouse locations for WebCore. The draggingLocation
+ // is in window coordinates. Both need to be flipped.
+ NSPoint windowPoint = [info draggingLocation];
+ NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+ NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+ gfx::Point transformedPt;
+ if (!webContents_->GetRenderWidgetHostView()) {
+ // TODO(ekaramad, paulmeyer): Find a better way than toggling |canceled_|.
+ // This could happen when the renderer process for the top-level RWH crashes
+ // (see https://crbug.com/670645).
+ canceled_ = true;
+ return NSDragOperationNone;
+ }
+
+ content::RenderWidgetHostImpl* targetRWH =
+ [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
+ if (![self isValidDragTarget:targetRWH])
+ return NSDragOperationNone;
+
+ currentRWHForDrag_ = targetRWH->GetWeakPtr();
+
// Fill out a DropData from pasteboard.
std::unique_ptr<DropData> dropData;
dropData.reset(new DropData());
[self populateDropData:dropData.get()
fromPasteboard:[info draggingPasteboard]];
- currentRVH_->FilterDropData(dropData.get());
+ // TODO(paulmeyer): Data may be pulled from the pasteboard multiple times per
+ // drag. Ideally, this should only be done once, and filtered as needed.
+ currentRWHForDrag_->FilterDropData(dropData.get());
NSDragOperation mask = [info draggingSourceOperationMask];
@@ -155,17 +190,9 @@ int GetModifierFlags() {
dropData_.swap(dropData);
- // Create the appropriate mouse locations for WebCore. The draggingLocation
- // is in window coordinates. Both need to be flipped.
- NSPoint windowPoint = [info draggingLocation];
- NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
- NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
- webContents_->GetRenderViewHost()->DragTargetDragEnter(
- *dropData_,
- gfx::Point(viewPoint.x, viewPoint.y),
- gfx::Point(screenPoint.x, screenPoint.y),
- static_cast<WebDragOperationsMask>(mask),
- GetModifierFlags());
+ currentRWHForDrag_->DragTargetDragEnter(
+ *dropData_, transformedPt, gfx::Point(screenPoint.x, screenPoint.y),
+ static_cast<WebDragOperationsMask>(mask), GetModifierFlags());
// We won't know the true operation (whether the drag is allowed) until we
// hear back from the renderer. For now, be optimistic:
@@ -187,15 +214,39 @@ int GetModifierFlags() {
if (delegate_)
delegate_->OnDragLeave();
- webContents_->GetRenderViewHost()->DragTargetDragLeave();
+ if (currentRWHForDrag_) {
+ currentRWHForDrag_->DragTargetDragLeave();
+ currentRWHForDrag_.reset();
+ }
dropData_.reset();
}
-- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
- view:(NSView*)view {
- DCHECK(currentRVH_);
- if (currentRVH_ != webContents_->GetRenderViewHost())
+- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info view:(NSView*)view {
+ if (canceled_) {
+ // TODO(ekaramad,paulmeyer): We probably shouldn't be checking for
+ // |canceled_| twice in this method.
+ return NSDragOperationNone;
+ }
+
+ // Create the appropriate mouse locations for WebCore. The draggingLocation
+ // is in window coordinates. Both need to be flipped.
+ NSPoint windowPoint = [info draggingLocation];
+ NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+ NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+ gfx::Point transformedPt;
+ content::RenderWidgetHostImpl* targetRWH =
+ [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
+
+ if (![self isValidDragTarget:targetRWH])
+ return NSDragOperationNone;
+
+ // TODO(paulmeyer): The dragging delegates may now by invoked multiple times
+ // per drag, even without the drag ever leaving the window.
+ if (targetRWH != currentRWHForDrag_.get()) {
+ if (currentRWHForDrag_)
+ currentRWHForDrag_->DragTargetDragLeave();
[self draggingEntered:info view:view];
+ }
if (canceled_)
return NSDragOperationNone;
@@ -206,17 +257,10 @@ int GetModifierFlags() {
return NSDragOperationNone;
}
- // Create the appropriate mouse locations for WebCore. The draggingLocation
- // is in window coordinates.
- NSPoint windowPoint = [info draggingLocation];
- NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
- NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
NSDragOperation mask = [info draggingSourceOperationMask];
- webContents_->GetRenderViewHost()->DragTargetDragOver(
- gfx::Point(viewPoint.x, viewPoint.y),
- gfx::Point(screenPoint.x, screenPoint.y),
- static_cast<WebDragOperationsMask>(mask),
- GetModifierFlags());
+ targetRWH->DragTargetDragOver(
+ transformedPt, gfx::Point(screenPoint.x, screenPoint.y),
+ static_cast<WebDragOperationsMask>(mask), GetModifierFlags());
if (delegate_)
delegate_->OnDragOver();
@@ -226,8 +270,23 @@ int GetModifierFlags() {
- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
view:(NSView*)view {
- if (currentRVH_ != webContents_->GetRenderViewHost())
+ // Create the appropriate mouse locations for WebCore. The draggingLocation
+ // is in window coordinates. Both need to be flipped.
+ NSPoint windowPoint = [info draggingLocation];
+ NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
+ NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
+ gfx::Point transformedPt;
+ content::RenderWidgetHostImpl* targetRWH =
+ [self GetRenderWidgetHostAtPoint:viewPoint transformedPt:&transformedPt];
+
+ if (![self isValidDragTarget:targetRWH])
+ return NO;
+
+ if (targetRWH != currentRWHForDrag_.get()) {
+ if (currentRWHForDrag_)
+ currentRWHForDrag_->DragTargetDragLeave();
[self draggingEntered:info view:view];
+ }
// Check if we only allow navigation and navigate to a url on the pasteboard.
if ([self onlyAllowsNavigation]) {
@@ -249,20 +308,34 @@ int GetModifierFlags() {
currentRVH_ = NULL;
- // Create the appropriate mouse locations for WebCore. The draggingLocation
- // is in window coordinates. Both need to be flipped.
- NSPoint windowPoint = [info draggingLocation];
- NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
- NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
- webContents_->GetRenderViewHost()->DragTargetDrop(
- *dropData_, gfx::Point(viewPoint.x, viewPoint.y),
- gfx::Point(screenPoint.x, screenPoint.y), GetModifierFlags());
+ targetRWH->DragTargetDrop(*dropData_, transformedPt,
+ gfx::Point(screenPoint.x, screenPoint.y),
+ GetModifierFlags());
dropData_.reset();
return YES;
}
+- (content::RenderWidgetHostImpl*)
+GetRenderWidgetHostAtPoint:(const NSPoint&)viewPoint
+ transformedPt:(gfx::Point*)transformedPt {
+ return webContents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+ webContents_->GetRenderViewHost()->GetWidget()->GetView(),
+ gfx::Point(viewPoint.x, viewPoint.y), transformedPt);
+}
+
+- (void)setDragStartTrackersForProcess:(int)processID {
+ dragStartProcessID_ = processID;
+ dragStartViewID_ = GetRenderViewHostID(webContents_->GetRenderViewHost());
+}
+
+- (bool)isValidDragTarget:(content::RenderWidgetHostImpl*)targetRWH {
+ return targetRWH->GetProcess()->GetID() == dragStartProcessID_ ||
+ GetRenderViewHostID(webContents_->GetRenderViewHost()) !=
+ dragStartViewID_;
+}
+
// Given |data|, which should not be nil, fill it in using the contents of the
// given pasteboard. The types handled by this method should be kept in sync
// with [WebContentsViewCocoa registerDragTypes].
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.h b/chromium/content/browser/web_contents/web_drag_source_mac.h
index 97590f86706..0bc51eb9292 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.h
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.h
@@ -9,10 +9,12 @@
#include "base/files/file_path.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
namespace content {
+class RenderWidgetHostImpl;
class WebContentsImpl;
struct DropData;
}
@@ -55,6 +57,9 @@ CONTENT_EXPORT
// The file UTI associated with the file drag, if any.
base::ScopedCFTypeRef<CFStringRef> fileUTI_;
+
+ // Tracks the RenderWidgetHost where the current drag started.
+ base::WeakPtr<content::RenderWidgetHostImpl> dragStartRWH_;
}
// Initialize a WebDragSource object for a drag (originating on the given
@@ -63,6 +68,7 @@ CONTENT_EXPORT
- (id)initWithContents:(content::WebContentsImpl*)contents
view:(NSView*)contentsView
dropData:(const content::DropData*)dropData
+ sourceRWH:(content::RenderWidgetHostImpl*)sourceRWH
image:(NSImage*)image
offset:(NSPoint)offset
pasteboard:(NSPasteboard*)pboard
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/browser/web_contents/web_drag_source_mac.mm
index 14321f47879..fdd46497ad4 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -22,6 +22,7 @@
#include "content/browser/download/drag_download_file.h"
#include "content/browser/download/drag_download_util.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -109,6 +110,7 @@ void PromiseWriterHelper(const DropData& drop_data,
- (id)initWithContents:(content::WebContentsImpl*)contents
view:(NSView*)contentsView
dropData:(const DropData*)dropData
+ sourceRWH:(content::RenderWidgetHostImpl*)sourceRWH
image:(NSImage*)image
offset:(NSPoint)offset
pasteboard:(NSPasteboard*)pboard
@@ -123,6 +125,7 @@ void PromiseWriterHelper(const DropData& drop_data,
dropData_.reset(new DropData(*dropData));
DCHECK(dropData_.get());
+ dragStartRWH_ = sourceRWH->GetWeakPtr();
dragImage_.reset([image retain]);
imageOffset_ = offset;
@@ -269,30 +272,31 @@ void PromiseWriterHelper(const DropData& drop_data,
operation:(NSDragOperation)operation {
if (!contents_ || !contentsView_)
return;
- contents_->SystemDragEnded();
-
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- contents_->GetRenderViewHost());
- if (rvh) {
- // Convert |screenPoint| to view coordinates and flip it.
- NSPoint localPoint = NSZeroPoint;
- if ([contentsView_ window])
- localPoint = [self convertScreenPoint:screenPoint];
- NSRect viewFrame = [contentsView_ frame];
- localPoint.y = viewFrame.size.height - localPoint.y;
- // Flip |screenPoint|.
- NSRect screenFrame = [[[contentsView_ window] screen] frame];
- screenPoint.y = screenFrame.size.height - screenPoint.y;
-
- // If AppKit returns a copy and move operation, mask off the move bit
- // because WebCore does not understand what it means to do both, which
- // results in an assertion failure/renderer crash.
- if (operation == (NSDragOperationMove | NSDragOperationCopy))
- operation &= ~NSDragOperationMove;
-
- contents_->DragSourceEndedAt(localPoint.x, localPoint.y, screenPoint.x,
- screenPoint.y, static_cast<blink::WebDragOperation>(operation));
- }
+
+ contents_->SystemDragEnded(dragStartRWH_.get());
+
+ // Convert |screenPoint| to view coordinates and flip it.
+ NSPoint localPoint = NSZeroPoint;
+ if ([contentsView_ window])
+ localPoint = [self convertScreenPoint:screenPoint];
+ NSRect viewFrame = [contentsView_ frame];
+ localPoint.y = viewFrame.size.height - localPoint.y;
+ // Flip |screenPoint|.
+ NSRect screenFrame = [[[contentsView_ window] screen] frame];
+ screenPoint.y = screenFrame.size.height - screenPoint.y;
+
+ // If AppKit returns a copy and move operation, mask off the move bit
+ // because WebCore does not understand what it means to do both, which
+ // results in an assertion failure/renderer crash.
+ if (operation == (NSDragOperationMove | NSDragOperationCopy))
+ operation &= ~NSDragOperationMove;
+
+ // TODO(paulmeyer): In the OOPIF case, should |localPoint| be converted to
+ // the coordinates local to |dragStartRWH_|?
+ contents_->DragSourceEndedAt(
+ localPoint.x, localPoint.y, screenPoint.x, screenPoint.y,
+ static_cast<blink::WebDragOperation>(operation),
+ dragStartRWH_.get());
// Make sure the pasteboard owner isn't us.
[pasteboard_ declareTypes:[NSArray array] owner:nil];
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
index 6f46e4f6317..29083eca01b 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
@@ -30,6 +30,7 @@ TEST_F(WebDragSourceMacTest, DragInvalidlyEscapedBookmarklet) {
initWithContents:contentsImpl
view:view
dropData:dropData.get()
+ sourceRWH:contentsImpl->GetRenderViewHost()->GetWidget()
image:nil
offset:NSZeroPoint
pasteboard:pasteboard1->get()
diff --git a/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
new file mode 100644
index 00000000000..4d881801d29
--- /dev/null
+++ b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
@@ -0,0 +1,77 @@
+// 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 <stddef.h>
+
+#include "base/command_line.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+
+static const char kGetDepthStreamAndCallCreateImageBitmap[] =
+ "getDepthStreamAndCallCreateImageBitmap";
+
+void RemoveSwitchFromCommandLine(base::CommandLine* command_line,
+ const std::string& switch_value) {
+ base::CommandLine::StringVector argv = command_line->argv();
+ const base::CommandLine::StringType switch_string =
+#if defined(OS_WIN)
+ base::ASCIIToUTF16(switch_value);
+#else
+ switch_value;
+#endif
+ argv.erase(std::remove_if(
+ argv.begin(), argv.end(),
+ [switch_string](const base::CommandLine::StringType& value) {
+ return value.find(switch_string) != std::string::npos;
+ }),
+ argv.end());
+ command_line->InitFromArgv(argv);
+}
+
+} // namespace
+
+namespace content {
+
+class WebRtcDepthCaptureBrowserTest : public WebRtcContentBrowserTestBase {
+ public:
+ WebRtcDepthCaptureBrowserTest() {
+ // Automatically grant device permission.
+ AppendUseFakeUIForMediaStreamFlag();
+ }
+ ~WebRtcDepthCaptureBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Test using two video capture devices - a color and a 16-bit depth device.
+ // By default, command line argument is present with no value. We need to
+ // remove it and then add the value defining two video capture devices.
+ const std::string fake_device_switch =
+ switches::kUseFakeDeviceForMediaStream;
+ ASSERT_TRUE(command_line->HasSwitch(fake_device_switch) &&
+ command_line->GetSwitchValueASCII(fake_device_switch).empty());
+ RemoveSwitchFromCommandLine(command_line, fake_device_switch);
+ command_line->AppendSwitchASCII(fake_device_switch, "device-count=2");
+ WebRtcContentBrowserTestBase::SetUpCommandLine(command_line);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(WebRtcDepthCaptureBrowserTest,
+ GetDepthStreamAndCallCreateImageBitmap) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(
+ embedded_test_server()->GetURL("/media/getusermedia-depth-capture.html"));
+ NavigateToURL(shell(), url);
+
+ ExecuteJavascriptAndWaitForOk(base::StringPrintf(
+ "%s({video: true});", kGetDepthStreamAndCallCreateImageBitmap));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 10c17d06e30..56a54ec109d 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -13,6 +13,8 @@
#include "base/trace_event/trace_event_impl.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
#include "content/browser/webrtc/webrtc_internals.h"
@@ -76,6 +78,23 @@ std::string GenerateGetUserMediaWithOptionalSourceID(
return function_name + "({" + audio_constraint + video_constraint + "});";
}
+std::string GenerateGetUserMediaWithDisableLocalEcho(
+ const std::string& function_name,
+ const std::string& disable_local_echo) {
+ const std::string audio_constraint =
+ "audio:{mandatory: { chromeMediaSource : 'system', disableLocalEcho : " +
+ disable_local_echo + " }},";
+
+ const std::string video_constraint =
+ "video: { mandatory: { chromeMediaSource:'screen' }}";
+ return function_name + "({" + audio_constraint + video_constraint + "});";
+}
+
+bool VerifyDisableLocalEcho(bool expect_value,
+ const content::StreamControls& controls) {
+ return expect_value == controls.disable_local_echo;
+}
+
} // namespace
namespace content {
@@ -93,7 +112,6 @@ class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase {
trace_log_ = base::trace_event::TraceLog::GetInstance();
base::trace_event::TraceConfig trace_config(
"video", base::trace_event::RECORD_UNTIL_FULL);
- trace_config.EnableSampling();
trace_log_->SetEnabled(trace_config,
base::trace_event::TraceLog::RECORDING_MODE);
// Check that we are indeed recording.
@@ -500,17 +518,10 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-#if defined(OS_WIN)
-// Timing out on Winodws 7 bot: http://crbug.com/443294
-#define MAYBE_TwoGetUserMediaWithFirst1080pSecondVga\
- DISABLED_TwoGetUserMediaWithFirst1080pSecondVga
-#else
-#define MAYBE_TwoGetUserMediaWithFirst1080pSecondVga\
- TwoGetUserMediaWithFirst1080pSecondVga
-#endif
-
+// Timing out on Windows 7 bot: http://crbug.com/443294
+// Flaky: http://crbug.com/660656; possible the test is too perf sensitive.
IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- MAYBE_TwoGetUserMediaWithFirst1080pSecondVga) {
+ DISABLED_TwoGetUserMediaWithFirst1080pSecondVga) {
std::string constraints1 =
"{video: {mandatory: {maxWidth:1920 , minWidth:1920 , maxHeight: 1080,\
minHeight: 1080}}}";
@@ -724,4 +735,32 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk(call);
}
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ DisableLocalEchoParameter) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ MediaStreamManager* manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
+
+ manager->SetGenerateStreamCallbackForTesting(
+ base::Bind(&VerifyDisableLocalEcho, false));
+ std::string call = GenerateGetUserMediaWithDisableLocalEcho(
+ "getUserMediaAndExpectSuccess", "false");
+ ExecuteJavascriptAndWaitForOk(call);
+
+ manager->SetGenerateStreamCallbackForTesting(
+ base::Bind(&VerifyDisableLocalEcho, true));
+ call = GenerateGetUserMediaWithDisableLocalEcho(
+ "getUserMediaAndExpectSuccess", "true");
+ ExecuteJavascriptAndWaitForOk(call);
+
+ manager->SetGenerateStreamCallbackForTesting(
+ MediaStreamManager::GenerateStreamTestCallback());
+}
+
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
index d6bc8707209..ca3751dad26 100644
--- a/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -18,29 +18,36 @@
#include "base/android/build_info.h"
#endif
+namespace content {
+
+#if defined(OS_WIN)
+// These tests are flaky on WebRTC Windows bots: https://crbug.com/633242.
+#define MAYBE_GetCapabilities DISABLED_GetCapabilities
+#define MAYBE_TakePhoto DISABLED_TakePhoto
+#define MAYBE_GrabFrame DISABLED_GrabFrame
+#else
+#define MAYBE_GetCapabilities GetCapabilities
+#define MAYBE_TakePhoto TakePhoto
+#define MAYBE_GrabFrame GrabFrame
+#endif
+
namespace {
static const char kImageCaptureHtmlFile[] = "/media/image_capture_test.html";
// TODO(mcasas): enable real-camera tests by disabling the Fake Device for
-// platforms where the ImageCaptureCode is landed, https://crbug.com/518807.
-// TODO(mcasas): enable in Android when takePhoto() can be specified a (small)
-// capture resolution preventing the test from timeout https://crbug.com/634811.
+// platforms where the ImageCaptureCode is landed, https://crbug.com/656810
static struct TargetCamera {
bool use_fake;
} const kTestParameters[] = {
-#if defined(OS_ANDROID)
{true},
+#if defined(OS_LINUX)
{false}
-#else
- {true}
#endif
};
} // namespace
-namespace content {
-
// This class is the content_browsertests for Image Capture API, which allows
// for capturing still images out of a MediaStreamTrack. Is a
// WebRtcWebcamBrowserTest to be able to use a physical camera.
@@ -63,85 +70,62 @@ class WebRtcImageCaptureBrowserTest
switches::kUseFakeDeviceForMediaStream));
}
- // Enables promised-based navigator.mediaDevices.getUserMedia();
- // TODO(mcasas): remove after https://crbug.com/503227 is closed.
+ // "GetUserMedia": enables navigator.mediaDevices.getUserMedia();
+ // TODO(mcasas): remove GetUserMedia after https://crbug.com/503227.
+ // "ImageCapture": enables the ImageCapture API.
+ // TODO(mcasas): remove ImageCapture after https://crbug.com/603328.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kEnableBlinkFeatures, "GetUserMedia");
-
- // Specific flag to enable ImageCapture API.
- // TODO(mcasas): remove after https://crbug.com/603328 is closed.
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kEnableBlinkFeatures, "ImageCapture");
+ switches::kEnableBlinkFeatures, "GetUserMedia,ImageCapture");
}
- private:
- DISALLOW_COPY_AND_ASSIGN(WebRtcImageCaptureBrowserTest);
-};
+ void SetUp() override {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ WebRtcWebcamBrowserTest::SetUp();
+ }
-#if defined(OS_WIN)
-// This test is flaky on WebRTC Windows bots: https://crbug.com/633242.
-#define MAYBE_CreateAndGetCapabilities DISABLED_CreateAndGetCapabilities
-#else
-#define MAYBE_CreateAndGetCapabilities CreateAndGetCapabilities
-#endif
-IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest,
- MAYBE_CreateAndGetCapabilities) {
+ // Tries to run a |command| JS test, returning true if the test can be safely
+ // skipped or it works as intended, or false otherwise.
+ bool RunImageCaptureTestCase(const std::string& command) {
#if defined(OS_ANDROID)
- // TODO(mcasas): fails on Lollipop devices: https://crbug.com/634811
- if (base::android::BuildInfo::GetInstance()->sdk_int() <
- base::android::SDK_VERSION_MARSHMALLOW) {
- return;
- }
+ // TODO(mcasas): fails on Lollipop devices: https://crbug.com/634811
+ if (base::android::BuildInfo::GetInstance()->sdk_int() <
+ base::android::SDK_VERSION_MARSHMALLOW) {
+ return true;
+ }
#endif
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url(embedded_test_server()->GetURL(kImageCaptureHtmlFile));
- NavigateToURL(shell(), url);
+ GURL url(embedded_test_server()->GetURL(kImageCaptureHtmlFile));
+ NavigateToURL(shell(), url);
- if (!IsWebcamAvailableOnSystem(shell()->web_contents())) {
- DVLOG(1) << "No video device; skipping test...";
- return;
- }
-
- std::string result;
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell(), "testCreateAndGetCapabilities()", &result));
- if (result == "OK")
- return;
- FAIL();
-}
+ if (!IsWebcamAvailableOnSystem(shell()->web_contents())) {
+ DVLOG(1) << "No video device; skipping test...";
+ return true;
+ }
-#if defined(OS_WIN)
-// This test is flaky on WebRTC Windows bots: https://crbug.com/633242.
-#define MAYBE_CreateAndTakePhoto DISABLED_CreateAndTakePhoto
-#else
-#define MAYBE_CreateAndTakePhoto CreateAndTakePhoto
-#endif
-IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest,
- MAYBE_CreateAndTakePhoto) {
-#if defined(OS_ANDROID)
- // TODO(mcasas): fails on Lollipop devices: https://crbug.com/634811
- if (base::android::BuildInfo::GetInstance()->sdk_int() <
- base::android::SDK_VERSION_MARSHMALLOW) {
- return;
+ std::string result;
+ if (!ExecuteScriptAndExtractString(shell(), command, &result))
+ return false;
+ DLOG_IF(ERROR, result != "OK") << result;
+ return result == "OK";
}
-#endif
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url(embedded_test_server()->GetURL(kImageCaptureHtmlFile));
- NavigateToURL(shell(), url);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebRtcImageCaptureBrowserTest);
+};
- if (!IsWebcamAvailableOnSystem(shell()->web_contents())) {
- DVLOG(1) << "No video device; skipping test...";
- return;
- }
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_GetCapabilities) {
+ embedded_test_server()->StartAcceptingConnections();
+ ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetCapabilities()"));
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_TakePhoto) {
+ embedded_test_server()->StartAcceptingConnections();
+ ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndTakePhoto()"));
+}
- std::string result;
- ASSERT_TRUE(ExecuteScriptAndExtractString(shell(), "testCreateAndTakePhoto()",
- &result));
- if (result == "OK")
- return;
- FAIL();
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_GrabFrame) {
+ embedded_test_server()->StartAcceptingConnections();
+ ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGrabFrame()"));
}
INSTANTIATE_TEST_CASE_P(,
diff --git a/chromium/content/browser/webrtc/webrtc_internals.cc b/chromium/content/browser/webrtc/webrtc_internals.cc
index d4a517e13d2..ec73946549c 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals.cc
@@ -50,19 +50,19 @@ static base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
} // namespace
WebRTCInternals::PendingUpdate::PendingUpdate(
- const std::string& command,
+ const char* command,
std::unique_ptr<base::Value> value)
: command_(command), value_(std::move(value)) {}
WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other)
- : command_(std::move(other.command_)),
+ : command_(other.command_),
value_(std::move(other.value_)) {}
WebRTCInternals::PendingUpdate::~PendingUpdate() {
DCHECK(thread_checker_.CalledOnValidThread());
}
-const std::string& WebRTCInternals::PendingUpdate::command() const {
+const char* WebRTCInternals::PendingUpdate::command() const {
DCHECK(thread_checker_.CalledOnValidThread());
return command_;
}
@@ -79,6 +79,7 @@ WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
: audio_debug_recordings_(false),
event_log_recordings_(false),
selecting_event_log_(false),
+ num_open_connections_(0),
should_block_power_saving_(should_block_power_saving),
aggregate_updates_ms_(aggregate_updates_ms),
weak_factory_(this) {
@@ -127,11 +128,13 @@ void WebRTCInternals::OnAddPeerConnection(int render_process_id,
dict->SetString("rtcConfiguration", rtc_configuration);
dict->SetString("constraints", constraints);
dict->SetString("url", url);
+ dict->SetBoolean("isOpen", true);
if (observers_.might_have_observers())
SendUpdate("addPeerConnection", dict->CreateDeepCopy());
peer_connection_data_.Append(std::move(dict));
+ ++num_open_connections_;
CreateOrReleasePowerSaveBlocker();
if (render_process_id_set_.insert(render_process_id).second) {
@@ -155,8 +158,8 @@ void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
if (this_pid != static_cast<int>(pid) || this_lid != lid)
continue;
+ MaybeClosePeerConnection(dict);
peer_connection_data_.Remove(i, NULL);
- CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers()) {
std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue());
@@ -183,6 +186,10 @@ void WebRTCInternals::OnUpdatePeerConnection(
if (this_pid != static_cast<int>(pid) || this_lid != lid)
continue;
+ if (type == "stop") {
+ MaybeClosePeerConnection(record);
+ }
+
// Append the update to the end of the log.
base::ListValue* log = EnsureLogList(record);
if (!log)
@@ -376,7 +383,7 @@ const base::FilePath& WebRTCInternals::GetEventLogFilePath() const {
return event_log_recordings_file_path_;
}
-void WebRTCInternals::SendUpdate(const string& command,
+void WebRTCInternals::SendUpdate(const char* command,
std::unique_ptr<base::Value> value) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(observers_.might_have_observers());
@@ -502,16 +509,29 @@ void WebRTCInternals::EnableEventLogRecordingsOnAllRenderProcessHosts() {
}
#endif
+void WebRTCInternals::MaybeClosePeerConnection(base::DictionaryValue* record) {
+ bool is_open;
+ bool did_read = record->GetBoolean("isOpen", &is_open);
+ DCHECK(did_read);
+ if (!is_open)
+ return;
+
+ record->SetBoolean("isOpen", false);
+ --num_open_connections_;
+ DCHECK_GE(num_open_connections_, 0);
+ CreateOrReleasePowerSaveBlocker();
+}
+
void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!should_block_power_saving_)
return;
- if (peer_connection_data_.empty() && power_save_blocker_) {
+ if (num_open_connections_ == 0 && power_save_blocker_) {
DVLOG(1) << ("Releasing the block on application suspension since no "
"PeerConnections are active anymore.");
power_save_blocker_.reset();
- } else if (!peer_connection_data_.empty() && !power_save_blocker_) {
+ } else if (num_open_connections_ != 0 && !power_save_blocker_) {
DVLOG(1) << ("Preventing the application from being suspended while one or "
"more PeerConnections are active.");
power_save_blocker_.reset(new device::PowerSaveBlocker(
@@ -527,9 +547,8 @@ void WebRTCInternals::ProcessPendingUpdates() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
while (!pending_updates_.empty()) {
const auto& update = pending_updates_.front();
- FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
- observers_,
- OnUpdate(update.command(), update.value()));
+ for (auto& observer : observers_)
+ observer.OnUpdate(update.command(), update.value());
pending_updates_.pop();
}
}
diff --git a/chromium/content/browser/webrtc/webrtc_internals.h b/chromium/content/browser/webrtc/webrtc_internals.h
index 111a7fa4cac..66f8cd1c4a1 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.h
+++ b/chromium/content/browser/webrtc/webrtc_internals.h
@@ -7,6 +7,7 @@
#include <memory>
#include <queue>
+#include <string>
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
@@ -108,6 +109,9 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
bool IsEventLogRecordingsEnabled() const;
const base::FilePath& GetEventLogFilePath() const;
+ int num_open_connections() { return num_open_connections_; }
+ bool IsPowerSavingBlocked() { return !!power_save_blocker_; }
+
protected:
// Constructor/Destructor are protected to allow tests to derive from the
// class and do per-instance testing without having to use the global
@@ -128,7 +132,7 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
FRIEND_TEST_ALL_PREFIXES(WebRtcInternalsTest,
AudioDebugRecordingsFileSelectionCanceled);
- void SendUpdate(const std::string& command,
+ void SendUpdate(const char* command,
std::unique_ptr<base::Value> value);
// RenderProcessHostObserver implementation.
@@ -153,9 +157,13 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
void EnableEventLogRecordingsOnAllRenderProcessHosts();
#endif
- // Called whenever an element is added to or removed from
- // |peer_connection_data_| to impose/release a block on suspending the current
- // application for power-saving.
+ // Updates the number of open PeerConnections. Called when a PeerConnection
+ // is stopped or removed.
+ void MaybeClosePeerConnection(base::DictionaryValue* record);
+
+ // Called whenever a PeerConnection is created or stopped in order to
+ // impose/release a block on suspending the current application for power
+ // saving.
void CreateOrReleasePowerSaveBlocker();
// Called on a timer to deliver updates to javascript.
@@ -203,9 +211,10 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
bool selecting_event_log_;
base::FilePath event_log_recordings_file_path_;
- // While |peer_connection_data_| is non-empty, hold an instance of
+ // While |num_open_connections_| is greater than zero, hold an instance of
// PowerSaveBlocker. This prevents the application from being suspended while
// remoting.
+ int num_open_connections_;
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
const bool should_block_power_saving_;
@@ -222,17 +231,17 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// thread.
class PendingUpdate {
public:
- PendingUpdate(const std::string& command,
+ PendingUpdate(const char* command,
std::unique_ptr<base::Value> value);
PendingUpdate(PendingUpdate&& other);
~PendingUpdate();
- const std::string& command() const;
+ const char* command() const;
const base::Value* value() const;
private:
base::ThreadChecker thread_checker_;
- std::string command_;
+ const char* command_;
std::unique_ptr<base::Value> value_;
DISALLOW_COPY_AND_ASSIGN(PendingUpdate);
};
diff --git a/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc b/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
index 841fcd1a26f..409fc90ef10 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
@@ -121,7 +121,7 @@ void WebRTCInternalsMessageHandler::OnDOMLoadDone(
}
}
-void WebRTCInternalsMessageHandler::OnUpdate(const std::string& command,
+void WebRTCInternalsMessageHandler::OnUpdate(const char* command,
const base::Value* args) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/webrtc/webrtc_internals_message_handler.h b/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
index 5b8d837cdd0..d5d21285f9a 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
+++ b/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
@@ -31,9 +31,6 @@ class CONTENT_EXPORT WebRTCInternalsMessageHandler
// WebUIMessageHandler implementation.
void RegisterMessages() override;
- // WebRTCInternalsUIObserver override.
- void OnUpdate(const std::string& command, const base::Value* args) override;
-
protected:
// The WebRTCInternals to use. Always WebRTCInternals::GetInstance()
// except for testing.
@@ -52,6 +49,9 @@ class CONTENT_EXPORT WebRTCInternalsMessageHandler
void OnSetEventLogRecordingsEnabled(bool enable, const base::ListValue* list);
void OnDOMLoadDone(const base::ListValue* list);
+ // WebRTCInternalsUIObserver override.
+ void OnUpdate(const char* command, const base::Value* args) override;
+
DISALLOW_COPY_AND_ASSIGN(WebRTCInternalsMessageHandler);
};
diff --git a/chromium/content/browser/webrtc/webrtc_internals_ui_observer.h b/chromium/content/browser/webrtc/webrtc_internals_ui_observer.h
index c78697057bb..8c8d381839e 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_ui_observer.h
+++ b/chromium/content/browser/webrtc/webrtc_internals_ui_observer.h
@@ -20,7 +20,7 @@ class WebRTCInternalsUIObserver {
// This is called on the browser IO thread. |args| can be NULL if there are no
// arguments.
- virtual void OnUpdate(const std::string& command,
+ virtual void OnUpdate(const char* command,
const base::Value* args) = 0;
};
diff --git a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
index c40d7fbe766..cfea70f19a6 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/webrtc/webrtc_internals.h"
#include <memory>
+#include <string>
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -17,9 +18,9 @@ namespace content {
namespace {
-static const std::string kContraints = "c";
-static const std::string kRtcConfiguration = "r";
-static const std::string kUrl = "u";
+static const char kContraints[] = "c";
+static const char kRtcConfiguration[] = "r";
+static const char kUrl[] = "u";
class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
public:
@@ -35,7 +36,7 @@ class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
}
private:
- void OnUpdate(const std::string& command, const base::Value* value) override {
+ void OnUpdate(const char* command, const base::Value* value) override {
command_ = command;
value_.reset(value ? value->DeepCopy() : nullptr);
if (loop_)
@@ -341,4 +342,53 @@ TEST_F(WebRtcInternalsTest, AudioDebugRecordingsFileSelectionCanceled) {
EXPECT_EQ(nullptr, observer.value());
}
+TEST_F(WebRtcInternalsTest, PowerSaveBlock) {
+ int kRenderProcessId = 1;
+ int pid = 1;
+ int lid[] = {1, 2, 3};
+
+ WebRTCInternalsForTest webrtc_internals;
+
+ // Add a few peer connections.
+ EXPECT_EQ(0, webrtc_internals.num_open_connections());
+ EXPECT_FALSE(webrtc_internals.IsPowerSavingBlocked());
+ webrtc_internals.OnAddPeerConnection(kRenderProcessId, pid, lid[0], kUrl,
+ kRtcConfiguration, kContraints);
+ EXPECT_EQ(1, webrtc_internals.num_open_connections());
+ EXPECT_TRUE(webrtc_internals.IsPowerSavingBlocked());
+
+ webrtc_internals.OnAddPeerConnection(kRenderProcessId, pid, lid[1], kUrl,
+ kRtcConfiguration, kContraints);
+ EXPECT_EQ(2, webrtc_internals.num_open_connections());
+ EXPECT_TRUE(webrtc_internals.IsPowerSavingBlocked());
+
+ webrtc_internals.OnAddPeerConnection(kRenderProcessId, pid, lid[2], kUrl,
+ kRtcConfiguration, kContraints);
+ EXPECT_EQ(3, webrtc_internals.num_open_connections());
+ EXPECT_TRUE(webrtc_internals.IsPowerSavingBlocked());
+
+ // Remove a peer connection without closing it first.
+ webrtc_internals.OnRemovePeerConnection(pid, lid[2]);
+ EXPECT_EQ(2, webrtc_internals.num_open_connections());
+ EXPECT_TRUE(webrtc_internals.IsPowerSavingBlocked());
+
+ // Close the remaining peer connections.
+ webrtc_internals.OnUpdatePeerConnection(pid, lid[1], "stop", std::string());
+ EXPECT_EQ(1, webrtc_internals.num_open_connections());
+ EXPECT_TRUE(webrtc_internals.IsPowerSavingBlocked());
+
+ webrtc_internals.OnUpdatePeerConnection(pid, lid[0], "stop", std::string());
+ EXPECT_EQ(0, webrtc_internals.num_open_connections());
+ EXPECT_FALSE(webrtc_internals.IsPowerSavingBlocked());
+
+ // Remove the remaining peer connections.
+ webrtc_internals.OnRemovePeerConnection(pid, lid[1]);
+ EXPECT_EQ(0, webrtc_internals.num_open_connections());
+ EXPECT_FALSE(webrtc_internals.IsPowerSavingBlocked());
+
+ webrtc_internals.OnRemovePeerConnection(pid, lid[0]);
+ EXPECT_EQ(0, webrtc_internals.num_open_connections());
+ EXPECT_FALSE(webrtc_internals.IsPowerSavingBlocked());
+}
+
} // namespace content
diff --git a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc
new file mode 100644
index 00000000000..14bb5cb184b
--- /dev/null
+++ b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.cc
@@ -0,0 +1,46 @@
+// 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/websockets/websocket_handshake_request_info_impl.h"
+
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+namespace {
+
+constexpr int g_tag = 0;
+
+} // namesapce
+
+WebSocketHandshakeRequestInfoImpl::WebSocketHandshakeRequestInfoImpl(
+ int child_id,
+ int render_frame_id)
+ : child_id_(child_id), render_frame_id_(render_frame_id) {}
+
+WebSocketHandshakeRequestInfoImpl::~WebSocketHandshakeRequestInfoImpl() {}
+
+void WebSocketHandshakeRequestInfoImpl::CreateInfoAndAssociateWithRequest(
+ int child_id,
+ int render_frame_id,
+ net::URLRequest* request) {
+ request->SetUserData(
+ &g_tag, new WebSocketHandshakeRequestInfoImpl(child_id, render_frame_id));
+}
+
+int WebSocketHandshakeRequestInfoImpl::GetChildId() const {
+ return child_id_;
+}
+
+int WebSocketHandshakeRequestInfoImpl::GetRenderFrameId() const {
+ return render_frame_id_;
+}
+
+const WebSocketHandshakeRequestInfo* WebSocketHandshakeRequestInfo::ForRequest(
+ const net::URLRequest* request) {
+ return static_cast<WebSocketHandshakeRequestInfoImpl*>(
+ request->GetUserData(&g_tag));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h
new file mode 100644
index 00000000000..4e768b1f11c
--- /dev/null
+++ b/chromium/content/browser/websockets/websocket_handshake_request_info_impl.h
@@ -0,0 +1,38 @@
+// 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_WEBSOCKET_WEBSOCKET_HANDSHAKE_REQUEST_INFO_IMPL_H_
+#define CONTENT_BROWSER_WEBSOCKET_WEBSOCKET_HANDSHAKE_REQUEST_INFO_IMPL_H_
+
+#include "content/public/browser/websocket_handshake_request_info.h"
+
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+
+namespace content {
+
+class WebSocketHandshakeRequestInfoImpl final
+ : public WebSocketHandshakeRequestInfo,
+ public base::SupportsUserData::Data {
+ public:
+ static void CreateInfoAndAssociateWithRequest(int child_id,
+ int render_frame_id,
+ net::URLRequest* request);
+
+ int GetChildId() const override;
+ int GetRenderFrameId() const override;
+
+ private:
+ WebSocketHandshakeRequestInfoImpl(int child_id, int render_frame_id);
+ ~WebSocketHandshakeRequestInfoImpl() override;
+
+ const int child_id_;
+ const int render_frame_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeRequestInfoImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEBSOCKET_WEBSOCKET_HANDSHAKE_REQUEST_INFO_IMPL_H_
diff --git a/chromium/content/browser/websockets/websocket_impl.cc b/chromium/content/browser/websockets/websocket_impl.cc
index 6ea179da371..7019bc5306d 100644
--- a/chromium/content/browser/websockets/websocket_impl.cc
+++ b/chromium/content/browser/websockets/websocket_impl.cc
@@ -22,6 +22,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
+#include "content/browser/websockets/websocket_handshake_request_info_impl.h"
#include "content/public/browser/storage_partition.h"
#include "ipc/ipc_message.h"
#include "net/base/io_buffer.h"
@@ -90,6 +91,7 @@ class WebSocketImpl::WebSocketEventHandler final
// net::WebSocketEventInterface implementation
+ void OnCreateURLRequest(net::URLRequest* url_request) override;
ChannelState OnAddChannelResponse(const std::string& selected_subprotocol,
const std::string& extensions) override;
ChannelState OnDataFrame(bool fin,
@@ -151,6 +153,12 @@ WebSocketImpl::WebSocketEventHandler::~WebSocketEventHandler() {
<< reinterpret_cast<void*>(this);
}
+void WebSocketImpl::WebSocketEventHandler::OnCreateURLRequest(
+ net::URLRequest* url_request) {
+ WebSocketHandshakeRequestInfoImpl::CreateInfoAndAssociateWithRequest(
+ impl_->child_id_, impl_->frame_id_, url_request);
+}
+
ChannelState WebSocketImpl::WebSocketEventHandler::OnAddChannelResponse(
const std::string& selected_protocol,
const std::string& extensions) {
@@ -354,15 +362,16 @@ void WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
callbacks_->ContinueSSLRequest();
}
-WebSocketImpl::WebSocketImpl(
- Delegate* delegate,
- blink::mojom::WebSocketRequest request,
- int frame_id,
- base::TimeDelta delay)
+WebSocketImpl::WebSocketImpl(Delegate* delegate,
+ blink::mojom::WebSocketRequest request,
+ int child_id,
+ int frame_id,
+ base::TimeDelta delay)
: delegate_(delegate),
binding_(this, std::move(request)),
delay_(delay),
pending_flow_control_quota_(0),
+ child_id_(child_id),
frame_id_(frame_id),
handshake_succeeded_(false),
weak_ptr_factory_(this) {
diff --git a/chromium/content/browser/websockets/websocket_impl.h b/chromium/content/browser/websockets/websocket_impl.h
index fb64613dc55..c6da13167ed 100644
--- a/chromium/content/browser/websockets/websocket_impl.h
+++ b/chromium/content/browser/websockets/websocket_impl.h
@@ -46,6 +46,7 @@ class CONTENT_EXPORT WebSocketImpl
WebSocketImpl(Delegate* delegate,
blink::mojom::WebSocketRequest request,
+ int child_id,
int frame_id,
base::TimeDelta delay);
~WebSocketImpl() override;
@@ -96,6 +97,7 @@ class CONTENT_EXPORT WebSocketImpl
// Zero indicates there is no pending SendFlowControl().
int64_t pending_flow_control_quota_;
+ int child_id_;
int frame_id_;
// handshake_succeeded_ is set and used by WebSocketManager to manage
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index 7dfb2948d5d..4d0e743c03d 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -15,7 +15,8 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "content/public/browser/storage_partition.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
namespace content {
@@ -43,6 +44,7 @@ class WebSocketManager::Handle : public base::SupportsUserData::Data,
// The network stack could be shutdown after this notification, so be sure to
// stop using it before then.
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, manager_);
manager_ = nullptr;
}
@@ -91,11 +93,28 @@ WebSocketManager::WebSocketManager(int process_id,
num_current_succeeded_connections_(0),
num_previous_succeeded_connections_(0),
num_current_failed_connections_(0),
- num_previous_failed_connections_(0) {}
+ num_previous_failed_connections_(0),
+ context_destroyed_(false) {
+ 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)));
+ }
+}
WebSocketManager::~WebSocketManager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!context_destroyed_ && url_request_context_getter_)
+ url_request_context_getter_->RemoveObserver(this);
+
for (auto impl : impls_) {
impl->GoAway();
delete impl;
@@ -114,12 +133,18 @@ void WebSocketManager::DoCreateWebSocket(
"Error in connection establishment: net::ERR_INSUFFICIENT_RESOURCES");
return;
}
+ if (context_destroyed_) {
+ request.ResetWithReason(
+ blink::mojom::WebSocket::kInsufficientResources,
+ "Error in connection establishment: net::ERR_UNEXPECTED");
+ return;
+ }
// Keep all WebSocketImpls alive until either the client drops its
// connection (see OnLostConnectionToClient) or we need to shutdown.
- impls_.insert(CreateWebSocketImpl(this, std::move(request), frame_id,
- CalculateDelay()));
+ impls_.insert(CreateWebSocketImpl(this, std::move(request), process_id_,
+ frame_id, CalculateDelay()));
++num_pending_connections_;
if (!throttling_period_timer_.IsRunning()) {
@@ -161,9 +186,11 @@ void WebSocketManager::ThrottlingPeriodTimerCallback() {
WebSocketImpl* WebSocketManager::CreateWebSocketImpl(
WebSocketImpl::Delegate* delegate,
blink::mojom::WebSocketRequest request,
+ int child_id,
int frame_id,
base::TimeDelta delay) {
- return new WebSocketImpl(delegate, std::move(request), frame_id, delay);
+ return new WebSocketImpl(delegate, std::move(request), child_id, frame_id,
+ delay);
}
int WebSocketManager::GetClientProcessId() {
@@ -195,4 +222,24 @@ void WebSocketManager::OnLostConnectionToClient(WebSocketImpl* impl) {
delete impl;
}
+void WebSocketManager::OnContextShuttingDown() {
+ context_destroyed_ = true;
+ url_request_context_getter_ = nullptr;
+ for (const auto& impl : impls_) {
+ impl->GoAway();
+ delete impl;
+ }
+ impls_.clear();
+}
+
+void WebSocketManager::ObserveURLRequestContextGetter() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!url_request_context_getter_->GetURLRequestContext()) {
+ context_destroyed_ = true;
+ url_request_context_getter_ = nullptr;
+ return;
+ }
+ url_request_context_getter_->AddObserver(this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/websockets/websocket_manager.h b/chromium/content/browser/websockets/websocket_manager.h
index bee498ae23d..8f1b9c9f689 100644
--- a/chromium/content/browser/websockets/websocket_manager.h
+++ b/chromium/content/browser/websockets/websocket_manager.h
@@ -9,9 +9,12 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/timer/timer.h"
#include "content/browser/websockets/websocket_impl.h"
#include "content/common/content_export.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_context_getter_observer.h"
namespace content {
class StoragePartition;
@@ -21,12 +24,16 @@ 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 WebSocketImpl::Delegate),
+ NON_EXPORTED_BASE(public net::URLRequestContextGetterObserver) {
public:
// Called on the UI thread:
static void CreateWebSocket(int process_id, int frame_id,
blink::mojom::WebSocketRequest request);
+ // net::URLRequestContextGetterObserver implementation.
+ void OnContextShuttingDown() override;
+
protected:
class Handle;
friend class base::DeleteHelper<WebSocketManager>;
@@ -45,6 +52,7 @@ class CONTENT_EXPORT WebSocketManager
virtual WebSocketImpl* CreateWebSocketImpl(
WebSocketImpl::Delegate* delegate,
blink::mojom::WebSocketRequest request,
+ int child_id,
int frame_id,
base::TimeDelta delay);
@@ -54,8 +62,11 @@ class CONTENT_EXPORT WebSocketManager
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_;
@@ -75,6 +86,8 @@ class CONTENT_EXPORT WebSocketManager
int64_t num_current_failed_connections_;
int64_t num_previous_failed_connections_;
+ bool context_destroyed_;
+
DISALLOW_COPY_AND_ASSIGN(WebSocketManager);
};
diff --git a/chromium/content/browser/websockets/websocket_manager_unittest.cc b/chromium/content/browser/websockets/websocket_manager_unittest.cc
index c2a90b80efd..22cb7c4d43f 100644
--- a/chromium/content/browser/websockets/websocket_manager_unittest.cc
+++ b/chromium/content/browser/websockets/websocket_manager_unittest.cc
@@ -23,9 +23,14 @@ class TestWebSocketImpl : public WebSocketImpl {
public:
TestWebSocketImpl(Delegate* delegate,
blink::mojom::WebSocketRequest request,
+ int process_id,
int frame_id,
base::TimeDelta delay)
- : WebSocketImpl(delegate, std::move(request), frame_id, delay) {}
+ : WebSocketImpl(delegate,
+ std::move(request),
+ process_id,
+ frame_id,
+ delay) {}
base::TimeDelta delay() const { return delay_; }
@@ -61,10 +66,11 @@ class TestWebSocketManager : public WebSocketManager {
private:
WebSocketImpl* CreateWebSocketImpl(WebSocketImpl::Delegate* delegate,
blink::mojom::WebSocketRequest request,
+ int process_id,
int frame_id,
base::TimeDelta delay) override {
- TestWebSocketImpl* impl =
- new TestWebSocketImpl(delegate, std::move(request), frame_id, delay);
+ TestWebSocketImpl* impl = new TestWebSocketImpl(
+ delegate, std::move(request), process_id, frame_id, delay);
// We keep a vector of sockets here to track their creation order.
sockets_.push_back(impl);
return impl;
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.cc b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
index bd5a9aeb3c1..1e52bc294fc 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
@@ -29,17 +29,17 @@ WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
if (!url.SchemeIs(kChromeUIScheme))
return WebUI::kNoWebUI;
- if (url.host() == kChromeUIWebRTCInternalsHost ||
+ if (url.host_piece() == kChromeUIWebRTCInternalsHost ||
#if !defined(OS_ANDROID)
- url.host() == kChromeUITracingHost ||
+ url.host_piece() == kChromeUITracingHost ||
#endif
- url.host() == kChromeUIGpuHost ||
- url.host() == kChromeUIIndexedDBInternalsHost ||
- url.host() == kChromeUIMediaInternalsHost ||
- url.host() == kChromeUIServiceWorkerInternalsHost ||
- url.host() == kChromeUIAccessibilityHost ||
- url.host() == kChromeUIAppCacheInternalsHost ||
- url.host() == kChromeUINetworkErrorsListingHost) {
+ url.host_piece() == kChromeUIGpuHost ||
+ url.host_piece() == kChromeUIIndexedDBInternalsHost ||
+ url.host_piece() == kChromeUIMediaInternalsHost ||
+ url.host_piece() == kChromeUIServiceWorkerInternalsHost ||
+ url.host_piece() == kChromeUIAccessibilityHost ||
+ url.host_piece() == kChromeUIAppCacheInternalsHost ||
+ url.host_piece() == kChromeUINetworkErrorsListingHost) {
return const_cast<ContentWebUIControllerFactory*>(this);
}
return WebUI::kNoWebUI;
@@ -60,27 +60,27 @@ WebUIController* ContentWebUIControllerFactory::CreateWebUIControllerForURL(
if (!url.SchemeIs(kChromeUIScheme))
return nullptr;
- if (url.host() == kChromeUIAppCacheInternalsHost)
+ if (url.host_piece() == kChromeUIAppCacheInternalsHost)
return new AppCacheInternalsUI(web_ui);
- if (url.host() == kChromeUIGpuHost)
+ if (url.host_piece() == kChromeUIGpuHost)
return new GpuInternalsUI(web_ui);
- if (url.host() == kChromeUIIndexedDBInternalsHost)
+ if (url.host_piece() == kChromeUIIndexedDBInternalsHost)
return new IndexedDBInternalsUI(web_ui);
- if (url.host() == kChromeUIMediaInternalsHost)
+ if (url.host_piece() == kChromeUIMediaInternalsHost)
return new MediaInternalsUI(web_ui);
- if (url.host() == kChromeUIAccessibilityHost)
+ if (url.host_piece() == kChromeUIAccessibilityHost)
return new AccessibilityUI(web_ui);
- if (url.host() == kChromeUIServiceWorkerInternalsHost)
+ if (url.host_piece() == kChromeUIServiceWorkerInternalsHost)
return new ServiceWorkerInternalsUI(web_ui);
- if (url.host() == kChromeUINetworkErrorsListingHost)
+ if (url.host_piece() == kChromeUINetworkErrorsListingHost)
return new NetworkErrorsListingUI(web_ui);
#if !defined(OS_ANDROID)
- if (url.host() == kChromeUITracingHost)
+ if (url.host_piece() == kChromeUITracingHost)
return new TracingUI(web_ui);
#endif
#if defined(ENABLE_WEBRTC)
- if (url.host() == kChromeUIWebRTCInternalsHost)
+ if (url.host_piece() == kChromeUIWebRTCInternalsHost)
return new WebRTCInternalsUI(web_ui);
#endif
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index 1b52b4d7155..03721b0c5e1 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -145,7 +145,8 @@ std::string SharedResourcesDataSource::GetMimeType(
return "text/plain";
}
-base::MessageLoop* SharedResourcesDataSource::MessageLoopForRequestPath(
+scoped_refptr<base::SingleThreadTaskRunner>
+SharedResourcesDataSource::TaskRunnerForRequestPath(
const std::string& path) const {
return nullptr;
}
diff --git a/chromium/content/browser/webui/shared_resources_data_source.h b/chromium/content/browser/webui/shared_resources_data_source.h
index 621c24d2882..a20d384de7a 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.h
+++ b/chromium/content/browser/webui/shared_resources_data_source.h
@@ -23,8 +23,8 @@ class SharedResourcesDataSource : public URLDataSource {
const ResourceRequestInfo::WebContentsGetter& wc_getter,
const URLDataSource::GotDataCallback& callback) override;
std::string GetMimeType(const std::string& path) const override;
- base::MessageLoop* MessageLoopForRequestPath(
- const std::string& path) const override;
+ scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForRequestPath(
+ const std::string& path) const override;
std::string GetAccessControlAllowOriginForOrigin(
const std::string& origin) const override;
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 84fcef5d113..72c035a2026 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -41,7 +41,8 @@
#include "content/public/common/url_constants.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/filter/filter.h"
+#include "net/filter/gzip_source_stream.h"
+#include "net/filter/source_stream.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/log/net_log_util.h"
@@ -143,7 +144,7 @@ class URLRequestChromeJob : public net::URLRequestJob {
bool GetMimeType(std::string* mime_type) const override;
int GetResponseCode() const override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
- std::unique_ptr<net::Filter> SetupFilter() const override;
+ std::unique_ptr<net::SourceStream> SetUpSourceStream() override;
// Used to notify that the requested data's |mime_type| is ready.
void MimeTypeAvailable(const std::string& mime_type);
@@ -393,8 +394,12 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
info->headers->AddHeader("Content-Encoding: gzip");
}
-std::unique_ptr<net::Filter> URLRequestChromeJob::SetupFilter() const {
- return is_gzipped_ ? net::Filter::GZipFactory() : nullptr;
+std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
+ std::unique_ptr<net::SourceStream> source =
+ net::URLRequestJob::SetUpSourceStream();
+ return is_gzipped_ ? net::GzipSourceStream::Create(
+ std::move(source), net::SourceStream::TYPE_GZIP)
+ : std::move(source);
}
void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
@@ -555,13 +560,13 @@ class ChromeProtocolHandler
// Next check for chrome://histograms/, which uses its own job type.
if (request->url().SchemeIs(kChromeUIScheme) &&
- request->url().host() == kChromeUIHistogramHost) {
+ request->url().host_piece() == kChromeUIHistogramHost) {
return new HistogramInternalsRequestJob(request, network_delegate);
}
// Check for chrome://network-error/, which uses its own job type.
if (request->url().SchemeIs(kChromeUIScheme) &&
- request->url().host() == kChromeUINetworkErrorHost) {
+ request->url().host_piece() == kChromeUINetworkErrorHost) {
// Get the error code passed in via the request URL path.
std::basic_string<char> error_code_string =
request->url().path().substr(1);
@@ -577,6 +582,13 @@ class ChromeProtocolHandler
}
}
+ // Check for chrome://dino which is an alias for chrome://network-error/-106
+ if (request->url().SchemeIs(kChromeUIScheme) &&
+ request->url().host() == kChromeUIDinoHost) {
+ return new net::URLRequestErrorJob(request, network_delegate,
+ net::Error::ERR_INTERNET_DISCONNECTED);
+ }
+
// Fall back to using a custom handler
return new URLRequestChromeJob(
request, network_delegate,
@@ -706,9 +718,9 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
}
// Forward along the request to the data source.
- base::MessageLoop* target_message_loop =
- source->source()->MessageLoopForRequestPath(path);
- if (!target_message_loop) {
+ scoped_refptr<base::SingleThreadTaskRunner> target_runner =
+ source->source()->TaskRunnerForRequestPath(path);
+ if (!target_runner) {
job->MimeTypeAvailable(source->source()->GetMimeType(path));
// Eliminate potentially dangling pointer to avoid future use.
job = nullptr;
@@ -724,13 +736,13 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
// is guaranteed because request for mime type is placed in the
// message loop before request for data. And correspondingly their
// replies are put on the IO thread in the same order.
- target_message_loop->task_runner()->PostTask(
+ target_runner->PostTask(
FROM_HERE, base::Bind(&GetMimeTypeOnUI, base::RetainedRef(source), path,
job->AsWeakPtr()));
// The DataSource wants StartDataRequest to be called on a specific thread,
// usually the UI thread, for this path.
- target_message_loop->task_runner()->PostTask(
+ target_runner->PostTask(
FROM_HERE, base::Bind(&URLDataManagerBackend::CallStartRequest,
base::RetainedRef(source), path, child_id,
wc_getter, request_id));
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.cc b/chromium/content/browser/webui/web_ui_data_source_impl.cc
index 5b258e359b3..a5364fbf2b2 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -5,10 +5,12 @@
#include "content/browser/webui/web_ui_data_source_impl.h"
#include <stddef.h>
+#include <stdint.h>
#include <string>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
@@ -73,9 +75,8 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
return parent_->deny_xframe_options_;
}
bool IsGzipped(const std::string& path) const override {
- if (!parent_->json_path_.empty() && path == parent_->json_path_)
- return false;
- return parent_->use_gzip_for_all_paths_;
+ return parent_->use_gzip_for_all_paths_ &&
+ parent_->excluded_paths_.find(path) == parent_->excluded_paths_.end();
}
private:
@@ -141,8 +142,16 @@ void WebUIDataSourceImpl::AddBoolean(const std::string& name, bool value) {
// replacements.
}
+void WebUIDataSourceImpl::AddInteger(const std::string& name, int32_t value) {
+ localized_strings_.SetInteger(name, value);
+}
+
void WebUIDataSourceImpl::SetJsonPath(const std::string& path) {
+ DCHECK(json_path_.empty());
+ DCHECK(!path.empty());
+
json_path_ = path;
+ ExcludePathFromGzip(json_path_);
}
void WebUIDataSourceImpl::AddResourcePath(const std::string &path,
@@ -163,6 +172,10 @@ void WebUIDataSourceImpl::DisableReplaceExistingSource() {
replace_existing_source_ = false;
}
+void WebUIDataSourceImpl::ExcludePathFromGzip(const std::string& path) {
+ excluded_paths_.insert(path);
+}
+
void WebUIDataSourceImpl::DisableContentSecurityPolicy() {
add_csp_ = false;
}
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 b121d2375c5..387209ebc3d 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -5,8 +5,11 @@
#ifndef CONTENT_BROWSER_WEBUI_WEB_UI_DATA_SOURCE_IMPL_H_
#define CONTENT_BROWSER_WEBUI_WEB_UI_DATA_SOURCE_IMPL_H_
+#include <stdint.h>
+
#include <map>
#include <string>
+#include <unordered_set>
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -34,6 +37,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
void AddLocalizedStrings(
const base::DictionaryValue& localized_strings) override;
void AddBoolean(const std::string& name, bool value) override;
+ void AddInteger(const std::string& name, int32_t value) override;
void SetJsonPath(const std::string& path) override;
void AddResourcePath(const std::string& path, int resource_id) override;
void SetDefaultResource(int resource_id) override;
@@ -46,6 +50,9 @@ class CONTENT_EXPORT WebUIDataSourceImpl
void DisableDenyXFrameOptions() override;
void DisableI18nAndUseGzipForAllPaths() override;
+ // When DisableI18nAndUseGzipForAllPaths is enabled, exclude the given |path|.
+ void ExcludePathFromGzip(const std::string& path);
+
protected:
~WebUIDataSourceImpl() override;
@@ -82,6 +89,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
int default_resource_;
std::string json_path_;
std::map<std::string, int> path_to_idr_map_;
+ std::unordered_set<std::string> excluded_paths_;
// The |replacements_| is intended to replace |localized_strings_|.
// TODO(dschuyler): phase out |localized_strings_| in Q1 2016. (Or rename
// to |load_time_flags_| if the usage is reduced to storing flags only).
diff --git a/chromium/content/browser/webui/web_ui_data_source_unittest.cc b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
index cf9729723ff..c39aa6b0246 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -103,17 +103,23 @@ TEST_F(WebUIDataSourceTest, EmptyStrings) {
StartDataRequest("strings.js", base::Bind(&EmptyStringsCallback));
}
-void SomeStringsCallback(scoped_refptr<base::RefCountedMemory> data) {
+void SomeValuesCallback(scoped_refptr<base::RefCountedMemory> data) {
std::string result(data->front_as<char>(), data->size());
+ EXPECT_NE(result.find("\"flag\":true"), std::string::npos);
+ EXPECT_NE(result.find("\"counter\":10"), std::string::npos);
+ EXPECT_NE(result.find("\"debt\":-456"), std::string::npos);
EXPECT_NE(result.find("\"planet\":\"pluto\""), std::string::npos);
EXPECT_NE(result.find("\"button\":\"foo\""), std::string::npos);
}
-TEST_F(WebUIDataSourceTest, SomeStrings) {
+TEST_F(WebUIDataSourceTest, SomeValues) {
source()->SetJsonPath("strings.js");
+ source()->AddBoolean("flag", true);
+ source()->AddInteger("counter", 10);
+ source()->AddInteger("debt", -456);
source()->AddString("planet", base::ASCIIToUTF16("pluto"));
source()->AddLocalizedString("button", kDummyStringId);
- StartDataRequest("strings.js", base::Bind(&SomeStringsCallback));
+ StartDataRequest("strings.js", base::Bind(&SomeValuesCallback));
}
void DefaultResourceFoobarCallback(scoped_refptr<base::RefCountedMemory> data) {
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index 880029a3ee1..3302fc21179 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -69,8 +69,7 @@ base::string16 WebUI::GetJavascriptCall(
}
WebUIImpl::WebUIImpl(WebContents* contents, const std::string& frame_name)
- : link_transition_type_(ui::PAGE_TRANSITION_LINK),
- bindings_(BINDINGS_POLICY_WEB_UI),
+ : bindings_(BINDINGS_POLICY_WEB_UI),
web_contents_(contents),
web_contents_observer_(new MainFrameNavigationObserver(this, contents)),
frame_name_(frame_name) {
@@ -108,14 +107,13 @@ void WebUIImpl::OnWebUISend(const GURL& source_url,
ProcessWebUIMessage(source_url, message, args);
}
-void WebUIImpl::RenderViewCreated(RenderViewHost* render_view_host) {
- controller_->RenderViewCreated(render_view_host);
+void WebUIImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
+ controller_->RenderFrameCreated(render_frame_host);
}
-void WebUIImpl::RenderViewReused(RenderViewHost* render_view_host,
- bool was_main_frame) {
- if (was_main_frame) {
- GURL site_url = render_view_host->GetSiteInstance()->GetSiteURL();
+void WebUIImpl::RenderFrameReused(RenderFrameHost* render_frame_host) {
+ if (!render_frame_host->GetParent()) {
+ GURL site_url = render_frame_host->GetSiteInstance()->GetSiteURL();
GetContentClient()->browser()->LogWebUIUrl(site_url);
}
}
@@ -140,14 +138,6 @@ void WebUIImpl::OverrideTitle(const base::string16& title) {
overridden_title_ = title;
}
-ui::PageTransition WebUIImpl::GetLinkTransitionType() const {
- return link_transition_type_;
-}
-
-void WebUIImpl::SetLinkTransitionType(ui::PageTransition type) {
- link_transition_type_ = type;
-}
-
int WebUIImpl::GetBindings() const {
return bindings_;
}
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 752f8395469..6693814f7f3 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -27,14 +27,14 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
WebUIImpl(WebContents* contents, const std::string& frame_name);
~WebUIImpl() override;
- // Called when a RenderView is created for a WebUI (reload after a renderer
- // crash) or when a WebUI is created for an RenderView (i.e. navigating from
+ // Called when a RenderFrame is created for a WebUI (reload after a renderer
+ // crash) or when a WebUI is created for a RenderFrame (i.e. navigating from
// chrome://downloads to chrome://bookmarks) or when both are new (i.e.
// opening a new tab).
- void RenderViewCreated(RenderViewHost* render_view_host);
+ void RenderFrameCreated(RenderFrameHost* render_frame_host);
- // Called when a RenderView is reused for the same WebUI type (i.e. reload).
- void RenderViewReused(RenderViewHost* render_view_host, bool was_main_frame);
+ // Called when a RenderFrame is reused for the same WebUI type (i.e. reload).
+ void RenderFrameReused(RenderFrameHost* render_frame_host);
// Called when the owning RenderFrameHost has started swapping out.
void RenderFrameHostSwappingOut();
@@ -46,8 +46,6 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
float GetDeviceScaleFactor() const override;
const base::string16& GetOverriddenTitle() const override;
void OverrideTitle(const base::string16& title) override;
- ui::PageTransition GetLinkTransitionType() const override;
- void SetLinkTransitionType(ui::PageTransition type) override;
int GetBindings() const override;
void SetBindings(int bindings) override;
bool HasRenderFrame() override;
@@ -113,7 +111,6 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// Options that may be overridden by individual Web UI implementations. The
// bool options default to false. See the public getters for more information.
base::string16 overridden_title_; // Defaults to empty string.
- ui::PageTransition link_transition_type_; // Defaults to LINK.
int bindings_; // The bindings from BindingsPolicy that should be enabled for
// this page.
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 7ed7c43f145..e47d4e70dc2 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -32,7 +32,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/shell/public/cpp/interface_registry.h"
+#include "services/service_manager/public/cpp/interface_registry.h"
namespace content {
namespace {
@@ -127,8 +127,8 @@ class PingTestWebUIController : public TestWebUIController {
~PingTestWebUIController() override {}
// WebUIController overrides:
- void RenderViewCreated(RenderViewHost* render_view_host) override {
- render_view_host->GetMainFrame()->GetInterfaceRegistry()->AddInterface(
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
+ render_frame_host->GetInterfaceRegistry()->AddInterface(
base::Bind(&PingTestWebUIController::CreateHandler,
base::Unretained(this)));
}